1. 程式人生 > >Mybatis中《insert》返回map、list及巢狀、association和collection分佈查詢及延遲載入(懶載入)(按需載入)

Mybatis中《insert》返回map、list及巢狀、association和collection分佈查詢及延遲載入(懶載入)(按需載入)

本文目錄類容目錄結構:

一、select返回值

  • 1、返回值記錄封裝為List
  • 2、返回值記錄封裝為map

二、select_resultMap

  • 1、自定義結果對映規則
  • 2、關聯查詢_級聯屬性封裝結果,即<result column="did" property="dept.id"/>的方式
  • 3、association巢狀結果集定義關聯物件封裝規則
  • 4、association分步查詢
  • 5、分步查詢&延遲載入(懶載入)(按需載入)
  • 6、collection定義關聯集合封裝規則
  • 7、collection分步查詢&延遲載入
  • 8、分步查詢傳遞多列值&fetchType
  • 9、discriminator鑑別器(不常用)

1、資料庫表:

員工表:

部門表:

2、新建實體

為了節省空間省略了set,get方法和建構函式

員工表:

@Alias("emp")
public class Employee {
	
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	private Department dept;
}

部門表: 

public class Department {
	
	private Integer id;
	private String departmentName;
	private List<Employee> emps;
}

一、select返回值

1、返回值記錄封裝為List

public List<Employee> getEmpsByLastNameLike(String lastName);

resultType:如果返回的是一個集合,要寫集合中元素的型別

<!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->
<!--resultType:如果返回的是一個集合,要寫集合中元素的型別  -->
<select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee">
	select * from tbl_employee where last_name like #{lastName}
</select>

2、返回值記錄封裝為map

2.1 多條記錄封裝一個map:Map<Integer,Employee>:鍵是這條記錄的主鍵,值是記錄封裝後的javaBean
     @MapKey:告訴mybatis封裝這個map的時候使用哪個屬性作為map的key

@MapKey("lastName")
public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
<!--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>

2.2  返回一條記錄的map;key就是列名,值就是對應的值

public Map<String, Object> getEmpByIdReturnMap(Integer id);
<!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
<select id="getEmpByIdReturnMap" resultType="map">
	select * from tbl_employee where id=#{id}
</select>

二、resultMap

<resultMap>的作用:對select查詢的結果按指定的規則進行封裝

1、自定義結果對映規則

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

<resultMap>:自定義某個javaBean的封裝規則,type:自定義規則的Java型別,id:唯一id方便引用

<id>和<result>指定主鍵列的封裝規則,id定義主鍵會底層有優化; column:指定哪一列; property:指定對應的javaBean屬性

<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>

2、關聯查詢_級聯屬性封裝結果,即<result column="did" property="dept.id"/>的方式

場景:查詢Employee的同時查詢員工對應的部門,即查詢Employee時裡面的Department也有資料;見實體Employee的結構

public Employee getEmpAndDept(Integer id);
<select id="getEmpAndDept" resultMap="MyDifEmp">
	SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
	d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
	WHERE e.d_id=d.id AND e.id=#{id}
</select>
<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>

3、association巢狀結果集定義關聯物件封裝規則

場景:查詢Employee的同時查詢員工對應的部門,即查詢Employee時裡面的Department也有資料;見實體Employee的結構

<association>:定義關聯的單個物件的封裝規則,可以指定聯合的javaBean物件;

                        property="dept":指定哪個屬性是聯合的物件;javaType:指定這個屬性物件的型別[不能省略]

public Employee getEmpAndDept(Integer id);
<select id="getEmpAndDept" resultMap="MyDifEmp">
	SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
	d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
	WHERE e.d_id=d.id AND e.id=#{id}
</select>
<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>

4、association分步查詢

public Employee getEmpByIdStep(Integer id);
 <select id="getEmpByIdStep" resultMap="MyEmpByStep">
 	select * from tbl_employee where id=#{id}
 </select>

<association>:定義關聯物件的封裝規則
                      select:表明當前屬性是呼叫select指定的方法查出的結果
                      column:指定將哪一列的值傳給這個方法

 流程:使用select指定的方法(傳入column指定的這列引數的值)查出物件,並封裝給property指定的屬性 

 <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>

此時,需要使用部門mapper中的方法:

public Department getDeptById(Integer id);
<!--public Department getDeptById(Integer id);  -->
<select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
	select id,dept_name departmentName from tbl_dept where id=#{id}
</select>

5、分步查詢&延遲載入(懶載入)(按需載入)
原來我們每次查詢Employee物件的時候,都將一起查詢出來;現在部門資訊在我們使用的時候再去查詢;
做法:在分段查詢的基礎之上,全域性配置檔案中,加上兩個配置:

<settings>
	<!--顯示的指定每個我們需要更改的配置的值,即使他是預設的。防止版本更新帶來的問題  -->
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

說明:執行第一個列印語句後,第二句發現還用到了部門,才去查部門的資訊並執行了sql語句; 

6、collection定義關聯集合封裝規則

場景:查出的部門中對應一個list的員工集合:

public Department getDeptByIdPlus(Integer id);
<!-- 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>

巢狀結果集的方式,使用collection標籤定義關聯的集合型別的屬性封裝規則

collection:定義關聯集合型別的屬性的封裝規則 
ofType:指定集合裡面元素的型別

<!--巢狀結果集的方式,使用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>

7、collection分步查詢&延遲載入

場景:查出的部門中對應一個list的員工集合:

public Department getDeptByIdStep(Integer id);
<!-- public Department getDeptByIdStep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
	select id,dept_name from tbl_dept where id=#{id}
</select>
<!-- collection:分段查詢 -->
<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep">
	<id column="id" property="id"/>
	<id column="dept_name" property="departmentName"/>
	<collection property="emps" 
		select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
		column="id"></collection>
</resultMap>

注意,這裡面會引用員工部門的語句,則 在員工的mapper中寫上對應的查詢方法:

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

全域性配置了延遲載入後,此處也會起作用,即用到的時候才會去查詢資料庫:

8、collection分步查詢傳遞多列值(多關聯條件)&fetchType

基於7的場景,collection分步查詢時,當包含集合物件有多個關聯條件,此時collection中的傳參方法如下

<collection property="emps" 
	select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
	column="{dId=id,key2=column2}">
</collection>

即使配置了全域性載入,此處也可以用 fetchType修改

fetchType="lazy":表示使用延遲載入;- eager:表示使用立即載入

<collection property="emps" 
	select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
	column="{dId=id,key2=column2}" fetchType="lazy">
</collection>

9、discriminator鑑別器(不常用)

<discriminator javaType=""></discriminator>
鑑別器:mybatis可以使用discriminator判斷某列的值,然後根據某列的值改變封裝行為
場景:封裝Employee:
          如果查出的是女生:就把部門資訊查詢出來,否則不查詢;
          如果是男生,把last_name這一列的值賦值給email;

對部門資訊進行分佈查詢:

public Employee getEmpByIdStep(Integer id);
 <select id="getEmpByIdStep" resultMap="MyEmpDis">
 	select * from tbl_employee where id=#{id}
 	<if test="_parameter!=null">
 		and 1=1
 	</if>
 </select>
<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" 
	 		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>

測試:

結果:女生,則查出了部門

 結果:男生,賦了值並沒有查出部門