Mybatis中映射配置文件用法介紹

Mybatis映射配置文件

1、獲取自增主鍵的值

	<!-- public void addEmp(Employee employee); -->
	<!-- parameterType:參數類型,可以省略, 
	獲取自增主鍵的值:
		mysql支持自增主鍵,自增主鍵值的獲取,mybatis也是利用statement.getGenreatedKeys();
		useGeneratedKeys="true";使用自增主鍵獲取主鍵值策略
		keyProperty;指定對應的主鍵屬性,也就是mybatis獲取到主鍵值以後,將這個值封裝給javaBean的哪個屬性
	-->
	<insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee"
		useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
		insert into tbl_employee(last_name,email,gender) 
		values(#{lastName},#{email},#{gender})
	</insert>

擴展:Oracle中不支持自增,Oracle使用序列來模擬自增;每次插入數據的主鍵是從序列中拿到的值,如下所示:

<!-- 
獲取非自增主鍵的值:
	Oracle不支持自增;Oracle使用序列來模擬自增;
	每次插入的數據的主鍵是從序列中拿到的值;如何獲取到這個值;
 -->
<insert id="addEmp" databaseId="oracle">
	<!-- 
	keyProperty:查出的主鍵值封裝給javaBean的哪個屬性
	order="BEFORE":當前sql在插入sql之前運行
		   AFTER:當前sql在插入sql之後運行
	resultType:查出的數據的返回值類型
	
	BEFORE運行順序:
		先運行selectKey查詢id的sql;查出id值封裝給javaBean的id屬性
		在運行插入的sql;就可以取出id屬性對應的值
	AFTER運行順序:
		先運行插入的sql(從序列中取出新值作爲id);
		再運行selectKey查詢id的sql;
	 -->
	<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
		<!-- 編寫查詢主鍵的sql語句 -->
		<!-- BEFORE-->
		select EMPLOYEES_SEQ.nextval from dual 
		<!-- AFTER:
		 select EMPLOYEES_SEQ.currval from dual -->
	</selectKey>
	
	<!-- 插入時的主鍵是從序列中拿到的 -->
	<!-- BEFORE:-->
	insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
	values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) 
	<!-- AFTER:
	insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
	values(employees_seq.nextval,#{lastName},#{email}) -->
</insert>

2、mybatis參數處理

​ a)單個參數:mybatis不會做特殊處理; #{參數名/任意名}:取出參數值。例:#{id}

​ b)多個參數:mybatis會做特殊處理,多個參數會被封裝成 一個map

key:param1...paramN,或者參數的索引也可以 value:傳入的參數值

​ 如果還按照單個參數的寫法#{id},#{lastName}就會拋異常(如下代碼),這裏多個參數取值就需要使用命名參數來解決問題,例子如下。

異常:
org.apache.ibatis.binding.BindingException: 
Parameter 'id' not found. 
Available parameters are [1, 0, param1, param2]
操作:
	方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
	取值:#{id},#{lastName}

​ 【命名參數】:明確指定封裝參數時map的key:@Param(“id”)
​ 多個參數會被封裝成 一個map:key:使用@Param註解指定的值 value:參數值 #{指定的key}取出對應的參數值

public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);

​ c)POJO

​ 若多個參數正好是我們業務邏輯的數據模型,我們就可以直接傳入pojo;#{屬性名}:取出傳入的pojo的屬性值

​ d)Map

​ 若多個參數不是業務模型中的數據,沒有對應的pojo,不經常使用,爲了方便,我們也可以傳入map
#{key}:取出map中對應的值

總結: 參數多時會封裝map,爲了不混亂,我們可以使用@Param來指定封裝時使用的key;

3、參數值獲取mybatis中#{}和${}的區別

​ #{}:可以獲取map中的值或者pojo對象屬性的值;
​ ${}:可以獲取map中的值或者pojo對象屬性的值;

select * from tbl_employee where id=${id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?
	區別:
		#{}:是以預編譯的形式,將參數設置到sql語句中;PreparedStatement;防止sql注入
		${}:取出的值直接拼裝在sql語句中;會有安全問題;
		大多情況下,我們去參數的值都應該去使用#{};
		原生jdbc不支持佔位符的地方我們就可以使用${}進行取值
	比如分表、排序。。。;按照年份分表拆分
		select * from ${year}_salary where xxx;
		select * from tbl_employee order by ${f_name} ${order}

4、取值時指定參數相關規則

​ #{}:更豐富的用法:
​ 規定參數的一些規則:
​ a)javaType、 jdbcType、 mode(存儲過程)、 numericScale、resultMap、 typeHandler、 jdbcTypeName、 expression(未來準備支持的功能);

​ b)jdbcType通常需要在某種特定的條件下被設置:
​ 在我們數據爲null的時候,有些數據庫可能不能識別mybatis對null的默認處理。比如Oracle(報錯);

​ c)JdbcType OTHER:無效的類型;因爲mybatis對所有的null都映射的是原生Jdbc的OTHER類型,oracle不能正確處理;由於全局配置中:jdbcTypeForNull=OTHER;oracle不支持;兩種辦法

	1、#{email,jdbcType=OTHER};
	2、jdbcTypeForNull=NULL
		<setting name="jdbcTypeForNull" value="NULL"/>	(這裏是在mybatis全局配置文件下配置)

5、映射文件—select_記錄封裝map

//多條記錄封裝一個map:Map<Integer,Employee>:鍵是這條記錄的主鍵,值是記錄封裝後的javaBean
//@MapKey:告訴mybatis封裝這個map的時候使用哪個屬性作爲map的key!!
@MapKey("lastName")
public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
<!--resultType:如果返回的是一個集合,要寫集合中元素的類型  -->
<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
 	<select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from tbl_employee where last_name like #{lastName}
 	</select> 

6、映射文件—select_resultMap自定義結果映射規則

<!--自定義某個javaBean的封裝規則
	type:自定義規則的Java類型
	id:唯一id方便引用
	  -->
	<resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp">
		<!--指定主鍵列的封裝規則
		id定義主鍵會底層有優化;
		column:指定哪一列
		property:指定對應的javaBean屬性
		  -->
		<id column="id" property="id"/>
		<!-- 定義普通列封裝規則 -->
		<result column="last_name" property="lastName"/>
		<!-- 其他不指定的列會自動封裝:我們只要寫resultMap就把全部的映射規則都寫上。 -->
		<result column="email" property="email"/>
		<result column="gender" property="gender"/>
	</resultMap>

<!-- resultMap:自定義結果集映射規則;  -->
<!-- public Employee getEmpById(Integer id); -->
    <select id="getEmpById"  resultMap="MySimpleEmp"> 
        select * from tbl_employee where id=#{id}
    </select>

7、映射文件_resultMap_關聯查詢_級聯屬性封裝結果

場景一:
查詢Employee的同時查詢員工對應的部門
Employee===Department
一個員工有與之對應的部門信息;
id last_name gender d_id did dept_name (private Department dept;)

方式一:聯合查詢:級聯屬性封裝結果集

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
	<id column="id" property="id"/>
	<result column="last_name" property="lastName"/>
	<result column="gender" property="gender"/>
	<result column="did" property="dept.id"/>
	<result column="dept_name" property="dept.departmentName"/>
</resultMap>

方式二:使用association定義關聯的單個對象的封裝規則

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
	<id column="id" property="id"/>
	<result column="last_name" property="lastName"/>
	<result column="gender" property="gender"/>
	
	<!--  association可以指定聯合的javaBean對象
	property="dept":指定哪個屬性是聯合的對象
	javaType:指定這個屬性對象的類型[不能省略]
	-->
	<association property="dept" javaType="com.atguigu.mybatis.bean.Department">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
	</association>
</resultMap>

8、映射文件_select_resultMap_關聯查詢_分佈查詢&延遲加載

使用association進行分步查詢:
1、先按照員工id查詢員工信息
2、根據查詢員工信息中的d_id值去部門表查出部門信息
3、部門設置到員工中;

	 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
	 	<id column="id" property="id"/>
	 	<result column="last_name" property="lastName"/>
	 	<result column="email" property="email"/>
	 	<result column="gender" property="gender"/>
	 	<!-- association定義關聯對象的封裝規則
	 		select:表明當前屬性是調用select指定的方法查出的結果
	 		column:指定將哪一列的值傳給這個方法
	 		
	 		流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性
	 	 -->
 		<association property="dept" 
	 		select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
	 		column="d_id">
 		</association>
	 </resultMap>
	 
	 <!--  public Employee getEmpByIdStep(Integer id);-->
	 <select id="getEmpByIdStep" resultMap="MyEmpByStep">
	 	select * from tbl_employee where id=#{id}
	 </select>	 

	 <!-- 可以使用延遲加載(懶加載);(按需加載)
	 	Employee==>Dept:
	 		我們每次查詢Employee對象的時候,都將一起查詢出來。
	 		部門信息在我們使用的時候再去查詢;
	 		分段查詢的基礎之上加上兩個配置:
	  -->
	<!--在mybatis的全局配置文件中添加懶加載配置-->
	<settings>	
		<setting name="lazyLoadingEnabled" value="true"/>
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings>

​ 場景二:
​ 查詢部門的時候將部門對應的所有員工信息也查詢出來:註釋在DepartmentMapper.xml中

<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
	select * from tbl_employee where d_id=#{deptId}
</select>

<!--嵌套結果集的方式,使用collection標籤定義關聯的集合類型的屬性封裝規則  -->
<!-- 
	public class Department {
			private Integer id;
			private String departmentName;
			private List<Employee> emps;//集合類型得使用collection
	 -->

	<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
		<!-- 
			collection定義關聯集合類型的屬性的封裝規則 
			ofType:指定集合裏面元素的類型
		-->
		<collection property="emps" ofType="com.atguigu.mybatis.bean.Employee">
			<!-- 定義這個集合中元素的封裝規則 -->
			<id column="eid" property="id"/>
			<result column="last_name" property="lastName"/>
			<result column="email" property="email"/>
			<result column="gender" property="gender"/>
		</collection>
	</resultMap>
	<!-- public Department getDeptByIdPlus(Integer id); -->
	<select id="getDeptByIdPlus" resultMap="MyDept">
		SELECT d.id did,d.dept_name dept_name,
				e.id eid,e.last_name last_name,e.email email,e.gender gender
		FROM tbl_dept d
		LEFT JOIN tbl_employee e
		ON d.id=e.d_id
		WHERE d.id=#{id}
	</select>
	

9、映射文件_select_resultMap_discriminator鑑別器

<!-- <discriminator javaType=""></discriminator>
		鑑別器:mybatis可以使用discriminator判斷某列的值,然後根據某列的值改變封裝行爲
		封裝Employee:
			如果查出的是女生:就把部門信息查詢出來,否則不查詢;
			如果是男生,把last_name這一列的值賦值給email;
	 -->
	 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis">
	 	<id column="id" property="id"/>
	 	<result column="last_name" property="lastName"/>
	 	<result column="email" property="email"/>
	 	<result column="gender" property="gender"/>
	 	<!--
	 		column:指定判定的列名
	 		javaType:列值對應的java類型  -->
	 	<discriminator javaType="string" column="gender">
	 		<!--女生  resultType:指定封裝的結果類型;不能缺少。/resultMap-->
	 		<case value="0" resultType="com.atguigu.mybatis.bean.Employee">
	 			<association property="dept" 
                             <!--這裏是從接口DepartmentMapper中拿到getDeptById方法-->
			 		select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
			 		column="d_id">
		 		</association>
	 		</case>
	 		<!--男生 ;如果是男生,把last_name這一列的值賦值給email; -->
	 		<case value="1" resultType="com.atguigu.mybatis.bean.Employee">
		 		<id column="id" property="id"/>
			 	<result column="last_name" property="lastName"/>
			 	<result column="last_name" property="email"/>
			 	<result column="gender" property="gender"/>
	 		</case>
	 	</discriminator>
	 </resultMap>

	 <select id="getEmpByIdStep" resultMap="MyEmpDis">
	 	select * from tbl_employee where id=#{id}
	 </select>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章