這是mybatis系列第9篇,沒看前文的建議先去【Java冢狐】公眾號中查看前文,方便理解和掌握,在上一篇中我們介紹了關于MyBatis的自動映射是如何開啟以及使用的,想必大家對于這方面的知識有所了解了,
今天要給大家帶來的主要是MyBatis延遲加載以及鑒別器相關方面的知識以及內容,
延遲加載
延遲加載介紹
所謂的延遲加載就是將資料加載時機推遲,其中比較典型的應用就是推遲嵌套查詢的執行時機,
因為在mybatis中經常用到關聯查詢,但是并不是任何時候都需要立即回傳關聯查詢結果,就比如查詢訂單資訊,并不一定需要及時回傳訂單對應的用戶資訊或者訂單詳情資訊等,所以當我們遇到這種情況時就需要一種機制,當需要查看關聯的資料時,再去執行對應的查詢,回傳需要的結果,
這種需求在mybatis中可以使用延遲加載機制來實作,
延遲加載2種設定方式
MyBatis對于延遲加載提供了兩種設定方式,分別是:
- 全域配置的方式
- sqlmap中配置的方式
從這兩種方式的名稱來看就能發現這兩種延遲加載的區別,第一種方法會對所有的關聯查詢有效,而第二種方法只會對相關設定的查詢有效,
下面我們就分別看一下這兩種延遲加載的使用方式,
全域配置延遲加載
要想實作全域配置延遲加載就要通過mybatis的組態檔,
mybatis組態檔中通過下面兩個屬性來控制延遲加載:
<settings>
<!--打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="https://www.cnblogs.com/javazhonghu/p/true"/>
<!-- 當為true的時候,呼叫任意延遲屬性,會去加載所有延遲屬性,如果為false,則呼叫某個屬性的時候,只會加載指定的屬性 -->
<setting name="aggressiveLazyLoading" value="https://www.cnblogs.com/javazhonghu/p/false"/>
</settings>
- lazyLoadingEnabled:這個屬性比較好理解,是否開啟延遲加載,默認為false,如果需要開啟延遲加載,將其設定為true
- aggressiveLazyLoading:當為true的時候,呼叫任意延遲屬性,會去加載所有延遲屬性,如果為false,則呼叫某個屬性的時候,只會加載指定的屬性
關于全域配置延遲加載的說明就是這些,下面我們來用一個具體的例子來說明下全域配置延遲加載是如何使用的,
需求
這次我們要使用MyBatis實作的需求就是通過訂單id查詢訂單的各種資訊,諸如:訂單用戶資訊、訂單明細串列,其中訂單用戶資訊和訂單明細資訊采用延遲加載的方式來進行獲取,
mybatis配置
按照前面的介紹第一步就是通過mybatis的組態檔來進行設定,如下所示:
<settings>
<!--打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="https://www.cnblogs.com/javazhonghu/p/true"/>
<!-- 當為true的時候,呼叫任意延遲屬性,會去加載所有延遲屬性,如果為false,則呼叫某個屬性的時候,只會加載指定的屬性 -->
<setting name="aggressiveLazyLoading" value="https://www.cnblogs.com/javazhonghu/p/true"/>
</settings>
OrderMapper.xml
進行全域配置的設定完畢以后,我們就進行我們正常開發的途徑,首先就是撰寫xml檔案,在xml檔案中撰寫我們的sql陳述句,
<resultMap id="orderModelMap1" type="com.zhonghu.chat09.demo5.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!-- 通過訂單中user_id作為條件,查詢下單人資訊 -->
<association property="userModel" select="com.zhonghu.chat09.demo5.mapper.UserMapper.getById1" column="user_Id"/>
<!-- 通過訂單id作為條件,查詢詳情串列 -->
<collection property="orderDetailModelList" select="com.zhonghu.chat09.demo5.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>
<select id="getById1" resultMap="orderModelMap1">
<![CDATA[
SELECT
a.id ,
a.user_id,
a.create_time,
a.up_time
FROM
orders a
WHERE
a.id = #{value}
]]>
</select>
上面的orderModelMap1元素下面有兩個關聯查詢,我們也寫一下,
UserMapper.xml
<!-- 根據用戶id查詢用戶資訊 -->
<select id="getById1" resultType="com.zhonghu.chat09.demo5.model.UserModel">
<![CDATA[
SELECT id,name FROM user where id = #{user_id}
]]>
</select>
OrderDetailMapper.xml
<!-- 根據訂單di查詢訂單明細串列 -->
<select id="getListByOrderId1" resultType="com.zhonghu.chat09.demo5.model.OrderDetailModel">
<![CDATA[
SELECT
a.id,
a.order_id AS orderId,
a.goods_id AS goodsId,
a.num,
a.total_price AS totalPrice
FROM
order_detail a
WHERE
a.order_id = #{order_id}
]]>
</select>
對應的3個Model
上面我們寫了三個xml,那么接來下我們撰寫一下xml對應的Model,
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderModel {
private Integer id;
private Integer userId;
private Long createTime;
private Long upTime;
private UserModel userModel;
//訂單詳情串列
private List<OrderDetailModel> orderDetailModelList;
}
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserModel {
private Integer id;
private String name;
}
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderDetailModel {
private Integer id;
private Integer orderId;
private Integer goodsId;
private Integer num;
private Double totalPrice;
}
測驗用例
寫完了Model,我們的代碼基本就大功告成了,接下來我們就來看一看延遲加載的使用效果,
com.zhonghu.chat09.demo5.Demo5Test#getById1
@Test
public void getById1() throws IOException {
//指定mybatis全域組態檔
mybatisConfig = "demo5/mybatis-config.xml";
this.before();
OrderModel orderModel = null;
try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
orderModel = mapper.getById1(1);
}
log.info("-------分割線--------");
log.info("{}", orderModel.getUserModel());
}
運行輸出
01:55.343 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
01:55.372 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Parameters: 1(Integer)
01:55.431 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - <== Total: 1
01:55.431 [main] INFO c.j.chat05.demo5.Demo5Test - -------分割線--------
01:55.432 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ==> Preparing: SELECT a.id, a.order_id AS orderId, a.goods_id AS goodsId, a.num, a.total_price AS totalPrice FROM order_detail a WHERE a.order_id = ?
01:55.432 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ==> Parameters: 1(Integer)
01:55.435 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - <== Total: 2
01:55.439 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ==> Preparing: SELECT id,name FROM user where id = ?
01:55.439 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ==> Parameters: 2(Integer)
01:55.441 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <== Total: 1
01:55.441 [main] INFO c.j.chat05.demo5.Demo5Test - UserModel(id=2, name=Java冢狐)
從日志中可以看出,總共有3次查詢,后面2次查詢在分割線之后出現的,說明是呼叫了orderModel.getUserModel()觸發后面2次查詢動作,
代碼中我們呼叫的是獲取用戶資訊,而訂單串列資訊也被加載了,這個主要是由于aggressiveLazyLoading被設定為true了,當使用到一個延遲加載的屬性時,其他的延遲加載的屬性也會被一起加載,所以觸發了2個關聯的查詢,
下面我們看看將aggressiveLazyLoading設定為false的效果
<settings>
<!--打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="https://www.cnblogs.com/javazhonghu/p/true"/>
<!-- 當為true的時候,呼叫任意延遲屬性,會去加載所有延遲屬性,如果為false,則呼叫某個屬性的時候,只會加載指定的屬性 -->
<setting name="aggressiveLazyLoading" value="https://www.cnblogs.com/javazhonghu/p/false"/>
</settings>
再次運行測驗用例輸出
12:19.236 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
12:19.268 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Parameters: 1(Integer)
12:19.336 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - <== Total: 1
12:19.337 [main] INFO c.j.chat05.demo5.Demo5Test - -------分割線--------
12:19.338 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ==> Preparing: SELECT id,name FROM user where id = ?
12:19.338 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ==> Parameters: 2(Integer)
12:19.340 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <== Total: 1
12:19.341 [main] INFO c.j.chat05.demo5.Demo5Test - UserModel(id=2, name=Java冢狐)
通過這兩次對比,我們可以很輕易的看出延遲加載開啟與否的效果區別,
sqlmap中設定延遲加載
上面的篇幅我們介紹了全域的延遲加載是如何起作用以及如何使用的,全域的方式會對所有的關聯查詢起效,影響范圍比較大,mybatis也提供了在關聯查詢中進行設定的方式,只會對當前設定的關聯查詢起效,
關聯查詢,一般我們使用association、collection,這兩個元素都有個屬性fetchType,通過這個屬性可以指定關聯查詢的加載方式,
fetchType有兩個值
- eager:立即加載
- lazy:延遲加載
下面我們來實作一個需求:還是通過訂單id查詢訂單資訊,并獲取關聯的用戶資訊、訂單詳細串列,用戶資訊我們要求立即加載,而訂單詳情我們要求延遲加載,
mapper xml如下
<resultMap id="orderModelMap2" type="com.zhonghu.chat09.demo5.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!-- 通過訂單中user_id作為條件,查詢下單人資訊 -->
<association property="userModel" fetchType="eager" select="com.zhonghu.chat09.demo5.mapper.UserMapper.getById1" column="user_Id"/>
<!-- 通過訂單id作為條件,查詢詳情串列 -->
<collection property="orderDetailModelList" fetchType="lazy" select="com.zhonghu.chat09.demo5.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>
<select id="getById2" resultMap="orderModelMap2">
<![CDATA[
SELECT
a.id ,
a.user_id,
a.create_time,
a.up_time
FROM
orders a
WHERE
a.id = #{value}
]]>
</select>
重點注意上面配置中association、collection這2個元素的fetchType屬性,eager表示立即加載,lazy表示延遲加載,
測驗用例
com.zhonghu.chat09.demo5.Demo5Test#getById2
@Test
public void getById2() throws IOException {
//指定mybatis全域組態檔
mybatisConfig = "demo5/mybatis-config2.xml";
this.before();
OrderModel orderModel = null;
try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
orderModel = mapper.getById2(1);
}
log.info("-------分割線--------");
log.info("{}", orderModel.getOrderDetailModelList());
}
運行輸出
36:54.284 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
36:54.321 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Parameters: 1(Integer)
36:54.385 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Preparing: SELECT id,name FROM user where id = ?
36:54.385 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Parameters: 2(Integer)
36:54.387 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <==== Total: 1
36:54.389 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - <== Total: 1
36:54.390 [main] INFO c.j.chat05.demo5.Demo5Test - -------分割線--------
36:54.392 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ==> Preparing: SELECT a.id, a.order_id AS orderId, a.goods_id AS goodsId, a.num, a.total_price AS totalPrice FROM order_detail a WHERE a.order_id = ?
36:54.392 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ==> Parameters: 1(Integer)
36:54.397 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - <== Total: 2
36:54.398 [main] INFO c.j.chat05.demo5.Demo5Test - [OrderDetailModel(id=1, orderId=1, goodsId=1, num=2, totalPrice=16.00), OrderDetailModel(id=2, orderId=1, goodsId=1, num=1, totalPrice=16.00)]
注意輸出中的分割線,可以分析得出,用戶資訊是和訂單資訊一起立即查出來的,而訂單詳情,是在我們呼叫orderModel.getOrderDetailModelList()獲取訂單串列的時候,采取懶加載的,
鑒別器(discriminator)
有時候,一個資料庫查詢可能會回傳多個不同的結果集(但總體上還是有一定的聯系的), 鑒別器(discriminator)元素就是被設計來應對這種情況的,鑒別器的概念很好理解——它很像 Java 語言中的 switch 陳述句,
discriminator標簽常用的兩個屬性如下:
- column:該屬性用于設定要進行鑒別比較值的列,
- javaType:該屬性用于指定列的型別,保證使用相同的java型別來比較值,
discriminator標簽可以有1個或多個case標簽,case標簽有一個比較重要的屬性:
- value:該值為discriminator指定column用來匹配的值,當匹配的時候,結果會走這個case關聯的映射,
我們使用鑒別器實作一個功能:通過訂單id查詢訂單資訊,當傳入的訂單id為1的時候,獲取訂單資訊及下單人資訊;當傳入的訂單id為2的時候,獲取訂單資訊、下單人資訊、訂單明細資訊;其他情況默認只查詢訂單資訊,
OrderMapper.xml
<resultMap id="orderModelMap1" type="com.zhonghu.chat09.demo6.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!-- 鑒別器 -->
<discriminator javaType="int" column="id">
<case value="https://www.cnblogs.com/javazhonghu/p/1">
<!--通過用戶id查詢用戶資訊-->
<association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
</case>
<case value="https://www.cnblogs.com/javazhonghu/p/2">
<!--通過用戶id查詢用戶資訊-->
<association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
<!--通過訂單id查詢訂單串列-->
<collection property="orderDetailModelList" select="com.zhonghu.chat09.demo6.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</case>
</discriminator>
</resultMap>
<select id="getById1" resultMap="orderModelMap1">
<![CDATA[
SELECT
a.id ,
a.user_id,
a.create_time,
a.up_time
FROM
orders a
WHERE
a.id = #{value}
]]>
</select>
注意上面的discriminator,這部分是關鍵,discriminator內部的case會和每行查詢結果中的id欄位進行匹配,匹配成功了case內部的關聯查詢會被執行,未匹配上的,只會走discriminator外部默認配置的映射映射規則,
UserMapper.xml
<!-- 通過用戶id查詢用戶資訊 -->
<select id="getById1" resultType="com.zhonghu.chat09.demo6.model.UserModel">
<![CDATA[
SELECT id,name FROM user where id = #{user_id}
]]>
</select>
OrderDetailMapper.xml
<!-- 通過訂單id查詢訂單明細串列 -->
<select id="getListByOrderId1" resultType="com.zhonghu.chat09.demo6.model.OrderDetailModel">
<![CDATA[
SELECT
a.id,
a.order_id AS orderId,
a.goods_id AS goodsId,
a.num,
a.total_price AS totalPrice
FROM
order_detail a
WHERE
a.order_id = #{order_id}
]]>
</select>
對應的3個Model類
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderModel {
private Integer id;
private Integer userId;
private Long createTime;
private Long upTime;
//用戶資訊
private UserModel userModel;
//訂單詳情串列
private List<OrderDetailModel> orderDetailModelList;
}
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserModel {
private Integer id;
private String name;
}
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderDetailModel {
private Integer id;
private Integer orderId;
private Integer goodsId;
private Integer num;
private Double totalPrice;
}
測驗用例
com.zhonghu.chat09.demo6.Demo6Test#getById1
@Test
public void getById1() throws IOException {
try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
//查詢訂單為1的
OrderModel orderModel = mapper.getById1(1);
log.info("{}", orderModel);
log.info("------------------------------------------------------------");
//查詢訂單為2的
orderModel = mapper.getById1(2);
log.info("{}", orderModel);
log.info("------------------------------------------------------------");
//查詢訂單為3的
orderModel = mapper.getById1(3);
log.info("{}", orderModel);
}
}
運行輸出
58:16.413 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
58:16.457 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Parameters: 1(Integer)
58:16.481 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Preparing: SELECT id,name FROM user where id = ?
58:16.481 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Parameters: 2(Integer)
58:16.488 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <==== Total: 1
58:16.489 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - <== Total: 1
58:16.489 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=1, userId=2, createTime=1610803573, upTime=1610803573, userModel=UserModel(id=2, name=Java冢狐), orderDetailModelList=null)
58:16.491 [main] INFO c.j.chat05.demo6.Demo6Test - ------------------------------------------------------------
58:16.491 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
58:16.492 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Parameters: 2(Integer)
58:16.493 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Preparing: SELECT id,name FROM user where id = ?
58:16.493 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Parameters: 1(Integer)
58:16.494 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <==== Total: 1
58:16.495 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====> Preparing: SELECT a.id, a.order_id AS orderId, a.goods_id AS goodsId, a.num, a.total_price AS totalPrice FROM order_detail a WHERE a.order_id = ?
58:16.495 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====> Parameters: 2(Integer)
58:16.505 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - <==== Total: 1
58:16.505 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - <== Total: 1
58:16.506 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=2, userId=1, createTime=1610803573, upTime=1610803573, userModel=UserModel(id=1, name=冢狐), orderDetailModelList=[OrderDetailModel(id=3, orderId=2, goodsId=1, num=1, totalPrice=8.00)])
58:16.506 [main] INFO c.j.chat05.demo6.Demo6Test - ------------------------------------------------------------
58:16.506 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
58:16.506 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - ==> Parameters: 3(Integer)
58:16.508 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById1 - <== Total: 1
58:16.509 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=3, userId=1, createTime=1610803573, upTime=1610803573, userModel=null, orderDetailModelList=null)
輸出中可以看出,訂單1查詢了2次,訂單2查詢了3次,訂單3查詢了1次;鑒別器算是一個不錯的功能,
繼承(extends)
繼承在java是三大特性之一,可以起到重用代碼的作用,而mybatis也有繼承的功能,和java中的繼承的作用類似,主要在resultMap中使用,可以重用其他resultMap中配置的映射關系,
用法
<resultMap extends="被繼承的resultMap的id"></resultMap>
案例
下面我們使用繼承來對上面的鑒別器的案例改造一下,優化一下代碼
OrderMapper.xml
<resultMap id="orderModelMap2" type="com.zhonghu.chat09.demo6.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!-- 鑒別器 -->
<discriminator javaType="int" column="id">
<case value="https://www.cnblogs.com/javazhonghu/p/1" resultMap="orderModelMap3" />
<case value="https://www.cnblogs.com/javazhonghu/p/2" resultMap="orderModelMap4" />
</discriminator>
</resultMap>
<resultMap id="orderModelMap3" type="com.zhonghu.chat09.demo6.model.OrderModel" extends="orderModelMap2">
<!--通過用戶id查詢用戶資訊-->
<association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
</resultMap>
<resultMap id="orderModelMap4" type="com.zhonghu.chat09.demo6.model.OrderModel" extends="orderModelMap3">
<!--通過訂單id查詢訂單串列-->
<collection property="orderDetailModelList" select="com.zhonghu.chat09.demo6.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>
<select id="getById2" resultMap="orderModelMap2">
<![CDATA[
SELECT
a.id ,
a.user_id,
a.create_time,
a.up_time
FROM
orders a
WHERE
a.id = #{value}
]]>
</select>
重點在于上面兩個extends屬性,上面orderModelMap3繼承了orderModelMap2中配置的映射關系(除鑒別器之外),自己又加入了一個association去查詢用戶資訊;orderModelMap4繼承了orderModelMap3,自己又加入了一個查詢訂單串列的collection元素,上面使用extends做到了代碼重用,其實和下面這塊代碼寫法效果一樣:
<resultMap id="orderModelMap2" type="com.zhonghu.chat09.demo6.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!-- 鑒別器 -->
<discriminator javaType="int" column="id">
<case value="https://www.cnblogs.com/javazhonghu/p/1" resultMap="orderModelMap3" />
<case value="https://www.cnblogs.com/javazhonghu/p/2" resultMap="orderModelMap4" />
</discriminator>
</resultMap>
<resultMap id="orderModelMap3" type="com.zhonghu.chat09.demo6.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!--通過用戶id查詢用戶資訊-->
<association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
</resultMap>
<resultMap id="orderModelMap4" type="com.zhonghu.chat09.demo6.model.OrderModel">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="create_time" property="createTime"/>
<result column="up_time" property="upTime"/>
<!--通過用戶id查詢用戶資訊-->
<association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
<!--通過訂單id查詢訂單串列-->
<collection property="orderDetailModelList" select="com.zhonghu.chat09.demo6.mapper.OrderDetailMapper.getListByOrderId1" column="id"/>
</resultMap>
<select id="getById2" resultMap="orderModelMap2">
<![CDATA[
SELECT
a.id ,
a.user_id,
a.create_time,
a.up_time
FROM
orders a
WHERE
a.id = #{value}
]]>
</select>
測驗用例
com.zhonghu.chat09.demo6.Demo6Test#getById2
@Test
public void getById2() throws IOException {
try (SqlSession sqlSession = this.sqlSessionFactory.openSession(true);) {
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
//查詢訂單為1的
OrderModel orderModel = mapper.getById2(1);
log.info("{}", orderModel);
log.info("------------------------------------------------------------");
//查詢訂單為2的
orderModel = mapper.getById2(2);
log.info("{}", orderModel);
log.info("------------------------------------------------------------");
//查詢訂單為3的
orderModel = mapper.getById2(3);
log.info("{}", orderModel);
}
}
運行輸出
39:55.936 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
39:55.969 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Parameters: 1(Integer)
39:55.986 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Preparing: SELECT id,name FROM user where id = ?
39:55.987 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Parameters: 2(Integer)
39:55.992 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <==== Total: 1
39:55.993 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - <== Total: 1
39:55.993 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=1, userId=2, createTime=1610803573, upTime=1610803573, userModel=UserModel(id=2, name=Java冢狐), orderDetailModelList=null)
39:55.994 [main] INFO c.j.chat05.demo6.Demo6Test - ------------------------------------------------------------
39:55.994 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
39:55.995 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Parameters: 2(Integer)
39:55.995 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====> Preparing: SELECT a.id, a.order_id AS orderId, a.goods_id AS goodsId, a.num, a.total_price AS totalPrice FROM order_detail a WHERE a.order_id = ?
39:55.996 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - ====> Parameters: 2(Integer)
39:56.000 [main] DEBUG c.j.c.d.m.O.getListByOrderId1 - <==== Total: 1
39:56.001 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Preparing: SELECT id,name FROM user where id = ?
39:56.004 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - ====> Parameters: 1(Integer)
39:56.005 [main] DEBUG c.j.c.d.mapper.UserMapper.getById1 - <==== Total: 1
39:56.005 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - <== Total: 1
39:56.005 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=2, userId=1, createTime=1610803573, upTime=1610803573, userModel=UserModel(id=1, name=冢狐), orderDetailModelList=[OrderDetailModel(id=3, orderId=2, goodsId=1, num=1, totalPrice=8.00)])
39:56.005 [main] INFO c.j.chat05.demo6.Demo6Test - ------------------------------------------------------------
39:56.005 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Preparing: SELECT a.id , a.user_id, a.create_time, a.up_time FROM orders a WHERE a.id = ?
39:56.006 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - ==> Parameters: 3(Integer)
39:56.007 [main] DEBUG c.j.c.d.mapper.OrderMapper.getById2 - <== Total: 1
39:56.007 [main] INFO c.j.chat05.demo6.Demo6Test - OrderModel(id=3, userId=1, createTime=1610803573, upTime=1610803573, userModel=null, orderDetailModelList=null)
總結
本篇開篇重點介紹了有關MyBatis的延遲加載的相關的內容,對其中的全域延遲加載和部分延遲加載進行了注重的介紹,介紹完延遲加載后,又介紹了一些與之相關的鑒別器和繼承的相關內容,
最后
- 如果覺得看完有識訓,希望能關注一下,順便給我點個贊,這將會是我更新的最大動力,感謝各位的支持
- 歡迎各位關注我的公眾號【java冢狐】,專注于java和計算機基礎知識,保證讓你看完有所識訓,不信你打我
- 求一鍵三連:點贊、轉發、在看,
- 如果看完有不同的意見或者建議,歡迎多多評論一起交流,感謝各位的支持以及厚愛,
——我是冢狐,和你一樣熱愛編程,
歡迎關注公眾號“Java冢狐”獲取最新訊息
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/262783.html
標籤:Java
上一篇:死磕Spring之IoC篇 - BeanDefinition 的加載階段(XML 檔案)
下一篇:hashMap原始碼學習
