(九) MyBatis從入門到入土——延遲加載、鑑別器以及繼承

這是mybatis系列第9篇,沒看前文的建議先去【Java冢狐】公衆號中查看前文,方便理解和掌握。在上一篇中咱們介紹了關於MyBatis的自動映射是如何開啓以及使用的,想必你們對於這方面的知識有所瞭解了。java

今天要給你們帶來的主要是MyBatis延遲加載以及鑑別器相關方面的知識以及內容。sql

延遲加載

延遲加載介紹

所謂的延遲加載就是將數據加載時機推遲,其中比較典型的應用就是推遲嵌套查詢的執行時機。數據庫

由於在mybatis中常常用到關聯查詢,可是並非任什麼時候候都須要當即返回關聯查詢結果。就好比查詢訂單信息,並不必定須要及時返回訂單對應的用戶信息或者訂單詳情信息等,因此當咱們遇到這種狀況時就須要一種機制,當須要查看關聯的數據時,再去執行對應的查詢,返回須要的結果。編程

這種需求在mybatis中可使用延遲加載機制來實現。mybatis

延遲加載2種設置方式

MyBatis對於延遲加載提供了兩種設置方式,分別是:app

  • 全局配置的方式
  • sqlmap中配置的方式

從這兩種方式的名稱來看就能發現這兩種延遲加載的區別,第一種方法會對全部的關聯查詢有效,而第二種方法只會對相關設置的查詢有效。測試

下面咱們就分別看一下這兩種延遲加載的使用方式。fetch

全局配置延遲加載

要想實現全局配置延遲加載就要經過mybatis的配置文件。優化

mybatis配置文件中經過下面兩個屬性來控制延遲加載:ui

<settings>
    <!--打開延遲加載的開關  -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 當爲true的時候,調用任意延遲屬性,會去加載全部延遲屬性,若是爲false,則調用某個屬性的時候,只會加載指定的屬性 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>
  • lazyLoadingEnabled:這個屬性比較好理解,是否開啓延遲加載,默認爲false,若是須要開啓延遲加載,將其設置爲true
  • aggressiveLazyLoading:當爲true的時候,調用任意延遲屬性,會去加載全部延遲屬性,若是爲false,則調用某個屬性的時候,只會加載指定的屬性

關於全局配置延遲加載的說明就是這些,下面咱們來用一個具體的例子來講明下全局配置延遲加載是如何使用的。

需求

此次咱們要使用MyBatis實現的需求就是經過訂單id查詢訂單的各類信息,諸如:訂單用戶信息、訂單明細列表。其中訂單用戶信息和訂單明細信息採用延遲加載的方式來進行獲取。

mybatis配置

按照前面的介紹第一步就是經過mybatis的配置文件來進行設置。以下所示:

<settings>
    <!--打開延遲加載的開關  -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 當爲true的時候,調用任意延遲屬性,會去加載全部延遲屬性,若是爲false,則調用某個屬性的時候,只會加載指定的屬性 -->
    <setting name="aggressiveLazyLoading" value="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="true"/>
    <!-- 當爲true的時候,調用任意延遲屬性,會去加載全部延遲屬性,若是爲false,則調用某個屬性的時候,只會加載指定的屬性 -->
    <setting name="aggressiveLazyLoading" value="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="1">
            <!--經過用戶id查詢用戶信息-->
            <association property="userModel" select="com.zhonghu.chat09.demo6.mapper.UserMapper.getById1" column="user_Id"/>
        </case>
        <case value="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="1" resultMap="orderModelMap3" />
        <case value="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="1" resultMap="orderModelMap3" />
        <case value="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冢狐」獲取最新消息

相關文章
相關標籤/搜索