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>
測試:
結果:女生,則查出了部門
結果:男生,賦了值並沒有查出部門