一、myBatis物件關係對映(多對一關係、一對多關係)
1、多對一關係:
---例子:多個員工同屬於一個部門。
(1)myBatis傳送 額外SQL:
■ 案例:員工表通過 dept_id 關聯 部門表,需求:查詢指定員工id、name、所屬的部門名稱的資訊。
//部門物件的介面、對映檔案省略,跟員工邏輯差不多
/* 員工物件的介面 */
public interface EmployeeMapper {
Employee get(Long id);
}
<!--員工物件的對映檔案-->
<!-- 解決列名和屬性名不匹配問題 -->
<resultMap id="BaseResultMap" type="Employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="dept_id" property="dept.id"/>
</resultMap>
<!-- 查詢操作 -->
<select id="get" resultMap="BaseResultMap">
select id, name, dept_id from employee2 where id = #{id}
</select>
/* 測試:查詢指定員工id、name、所屬的部門名稱的資訊 */
@Test
public void testGet() throws Exception {
SqlSession session = MyBatisUtil.getSession();
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee e = employeeMapper.get(1L);
System.out.println(e);
//需要通過查詢得到的dept_id查詢獲取得到部門物件
/**
* 額外的查詢語句,可以通過配置resultMap的association屬性,讓myBatis幫我們執行
*/
//手動新增額外查詢語句
// Long dept_id = e.getDept().getId();
// DepartmentMapper departmentMapper = session.getMapper(DepartmentMapper.class);
// Department d = departmentMapper.get(dept_id);
// e.setDept(d);
System.out.println(e.getDept());
session.commit();
session.close();
}
-
上面是通過手動新增的額外SQL查詢,通過配置resultMap的association屬性,讓myBatis幫我們執行如下:
<!-- 解決列名和屬性名不匹配問題 -->
<resultMap id="BaseResultMap" type="Employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="dept_id" property="dept.id"/> -->
<!-- 額外的SQL配置方式
association元素:配置單一元素的關聯關係
property 屬性:物件的屬性
select 屬性:傳送額外的sql
column 屬性: 將指定的列的值傳遞給額外sql
-->
<association property="dept"
select="com.shan.hello.mappe r.DepartmentMapper.get"
column="dept_id"
/>
</resultMap>
(2)使用額外的 SQL 做對映配置
會導致的問題:N+1問題
例如:每個員工的部門編號dept_id 是不同的,當查詢所有員工的id、name、所屬的部門名稱的資訊時就會傳送額外N條SQL語句。
-
N:傳送額外N條SQL語句去查詢員工所屬的部門名稱: select name from department where id = dept_id;
-
1:查詢所有員工的id、name、所屬的部門的編號dept_id:select * from employee;
----解決:使用內聯對映
(多表查詢),此時一條 SQL 語句搞定。
----處理多表查詢的結果集的方法:內聯對映
。
(3)物件關聯的查詢:
方式一:額外的SQL
方式二:內聯對映
(4)處理多表查詢的結果集的方法【內聯對映】:
-
方式一:屬性名-列名 通過resultMap的
子元素result
進行對映配置[內聯對映-使用result]:
-
方式二:屬性名-列名 通過resultMap的
子元素association
進行對映配置[內聯對映-使用association]
(5)多對一關係配置總結:
★使用association元素
,配置單一物件屬性。
- 方式一:額外的SQL[分步查詢],一般需要進入另外一個頁面展示更加詳細的資訊。
- 方式二:內聯對映[多表查詢],常用。需要在列表中顯示關聯物件的資料,使用內聯對映,否則會出現N+1問題。
2、一對多關係配置:
---例子:一個部門有多個員工。
(1)一對多關係-額外的SQL:
<!-- 針對單一物件的屬性,使用association元素 -->
<!-- 針對集合型別的屬性,使用collection元素 -->
<!-- 額外的SQL配置方式
collection元素:配置集合型別元素的關聯關係
property 屬性:物件的屬性
select 屬性:傳送額外的sql
column 屬性: 將指定的列的值傳遞給額外sql
-->
<resultMap id="BaseResultMap" type="Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="" property="emps"/> -->
<collection property="emps"
select="com.shan.hello.mapper.EmployeeMapper.get"
column="id" >
</collection>
</resultMap>
<select id="get" resultMap="BaseResultMap">
select id, name from department where id = #{id}
</select>
(2)一對多關係-內聯查詢:
<!-- 針對單一物件的屬性,使用association元素 -->
<!-- 針對集合型別的屬性,使用collection元素 -->
<resultMap id="BaseResultMap" type="Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<!--<result column="" property="emps"/> -->
<!--
內聯查詢:ofType是集合中泛型的型別
-->
<collection property="emps" ofType="Employee">
<result column="e_id" property="id"/>
<result column="e_name" property="name"/>
<result column="e_dept_id" property="deptId"/>
</collection>
</resultMap>
<select id="get" resultMap="BaseResultMap">
<!-- select id, name from department where id = #{id} -->
select d.id, d.name, e.id e_id, e.name e_name, e.dept_id e_dept_id from department d
join employee2 e on d.id = e.dept_id where d.id = #{id}
</select>
二、設定延遲/懶載入
<!-- 全域性配置檔案 -->
<settings>
<!-- 懶載入/延遲載入,開啟延遲載入功能 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 設定不要積極地去查詢關聯物件 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 延遲載入的觸發方法 -->
<setting name="lazyLoadTriggerMethods" value="close"/>
</settings>
- 動態代理-增強功能--延遲載入
總結:多對一、一對多關係的單屬性物件/集合屬性物件,使用association或collection元素?使用額外SQL或內聯查詢?
-
針對【單屬性物件】:使用
assoication元素
,通常需要使用多表查詢操作,即內聯查詢
-
針對【集合屬性物件】:使用
collection元素
,通常還要使用延遲載入,即額外SQL處理