一:延遲加載
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的延遲加載機制的理解,有不足之處還請指出