MyBatis中的延遲加載策略


一:延遲加載

1.了解延遲加載:

延遲加載又叫懶加載,也叫按需加載,也就是說先加載主信息,需要的時候,再去加載從信息。代碼中有查詢語句,當執行到查詢語句時,並不是馬上去DB中查詢,而是根據設置的延遲策略將查詢向后推遲。

2.延遲加載的好處:

先從單表查詢、需要時再從關聯表去關聯查詢,大大提高數據庫性能,減輕數據庫服務器的壓力,因為查詢單表要比關聯查詢多張表速度要快。

3.如何開啟MyBatis的延遲加載:

Mybatis的延遲加載功能默認是關閉的

需要在mybatis-config.xml(mybatis的核心配置)文件中通過setting標簽配置來開啟延遲加載功能

 

<settings>
<!--開啟延遲加載-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value為true時為侵入式延遲加載,false為深入式延遲加載-->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>

4.延遲加載的resultMap

4.1當在resultMao中使用過association或者collection進行關系映射之后才能使用MyBatis的延遲加載策略

4.2 延遲加載需要兩個select語句來完成

關聯對象的查詢與主加載對象的查詢必須是分別進行的select語句,不能是使用多表連接所進行的select查詢。因為,多表連接查詢,實質是對一張表的查詢,對由多個表連接后形成的一張表的查詢。會一次性將多張表的所有信息查詢出來。

5.關聯對象的加載時機

MyBatis的延遲加載只是對關聯對象的查詢有延遲設置,對於主加載對象都是直接執行查詢語句的。

1.直接加載

即執行對象的select語句,完成對主加載馬上執行對關聯對象的select查詢。

2.侵入式延遲加載(aggressiveLazyLoading) 也可看做立即加載

執行對主加載對象的查詢時,不會執行對關聯對象的查詢。但是當要訪問主加載對象的詳情時馬上執行對關聯對象的select查詢。即對關聯對象的執行查詢,侵入到了主加載對象的訪問詳情中。也可理解為:將關聯對象的詳情侵入到主加載對象的詳情中去,即將關聯對象的詳情作為主加載對象的一部分出現了!

3.深度延遲加載

執行對主加載對象的查詢時,不會執行對關聯對象的查詢。訪問主加載對象的詳情時也不會執行關聯對象的select查詢。只有當真正訪問關聯對象的詳情時,才會執行對關聯對象的select查詢。

六:延遲加載測試案例

1.將倆張表的關聯關系在實體類中體現出來,也就是在一張表中添加另一張表的對象

 

 

2.創建Dao層的方法一級Mapper.xml文件

 

 

 

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjc.dao.ISmbmsDao">
    <resultMap id="SmbmsProviderResult" type="SmbmsBill">
        <collection property="smbmsProvider" ofType="SmbmsProvider" select="getSmbmsProvider" column="providerId">
        </collection>

    </resultMap>
    <select id="getSmbmsBillList" resultMap="SmbmsProviderResult">
        select * from  smbms.smbms_bill where id=#{id}
    </select>
    <select id="getSmbmsProvider" resultType="SmbmsProvider">
        select * from  smbms.smbms_provider where  id=#{providerId}
    </select>

</mapper>

3.測試類

public class YiTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtils.getSession();
        ISmbmsDao mapper = session.getMapper(ISmbmsDao.class);
        SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1);
}
}

當沒有開啟延遲加載策略的時候,MyBatis默認是直接加載當執行上面的測試類的時候結果如下

1.直接加載

 

 

 如上圖所示,一共向數據庫發送了兩條請求,此時我們開啟侵入式延遲加載 然后再執行上面的測試

2.侵入式延遲加載

<settings>
<!--開啟延遲加載-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value為true時為侵入式延遲加載,false為深入式延遲加載-->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>

此時測試的結果如下

 

 由於我們只進行了查詢操作,並沒有對查詢出來的主對象進行操作(訪問改對象的屬性或及方法)所以此時並沒有進行加載關聯的查詢

那么我們接下來訪問一些主對象的一些屬性

結果如下

 

 

這就是侵入式延遲加載的效果,當對主加載對象進行操作的時候就會去加載關聯對象(向數據庫發送請求)

3.深度式延遲加載

在核心配置文件中修改setting節點

          <!--開啟延遲加載-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--value為true時為侵入式延遲加載,false為深入式延遲加載-->
        <setting name="aggressiveLazyLoading" value="false"/>    

修改完成之后繼續執行上次執行的測試方法

 

 從上面的結果中可以看到同樣的測試方法,開始深度式延遲之后只向數據庫發送了一次請求,這是因為我們在測試類中只訪問了主對象的屬性,並沒有使用關聯對象的任何屬性

那么接下來我們修改測試類,在測試類中添加對關聯對象的訪問

public class YiTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtils.getSession();
        ISmbmsDao mapper = session.getMapper(ISmbmsDao.class);
        SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1);
        //獲取關聯對象中的proName屬性
        System.out.println(smbmsBillList.getSmbmsProvider().getProName());

    }
}

測試結果如下

 

 當我們訪問關聯對象時候就發送請求進行對關聯關系的加載,這就是MyBatis中的深度式延遲加載策略

以上就是我對MyBatis的延遲加載機制的理解,有不足之處還請指出

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM