【Mybatis架構】 延遲加載


 在上一篇博客中,我們提到過有關於Mybatis輸出映射中resultMap能夠實現延遲加載的事,然而真的是所有的resultMap都能實現延遲加載還是咋地啊?現在我們就來對那一句話做一下闡述和實例說明。

 

一、首先我們要知道什么是延遲加載?

       延遲加載機制是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正需要數據的時候,才真正執行數據加載操作;可以簡單理解為,只有在使用的時候,才會發出sql語句進行查詢;延遲加載的有效期是在session打開的情況下,當session關閉后,會報異常。當調用load方法加載對象時,返回代理對象,等到真正用到對象的內容時才發出sql語句。

 

總結:需要查詢關聯信息時,使用mybatis延遲加載特性可有效的減少數據庫壓力,首次查詢只查詢主要信息,              關聯信息等用戶獲取時再加載。我們已知的除了hibernate,還有我們的Mybatis。

 

二、實戰演練場:

(1)需求:還以我們的上面兩篇文章的電商項目查詢訂單信息為例,這次,我們以訂單信息為主要查詢表,然后關聯查詢對應的用戶信息。那什么是延遲加載呢,就是我們默認先只查詢訂單信息,當我們需要客戶信息的時候呢,我們再去關聯查詢用戶信息。這就是延遲加載了。

 

(2)pojo類的設計:

首先是訂單類:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public class Orders {  
  2.     private Integer id;  
  3.     private Integer userId;  
  4.     private String number;  
  5.     private Date createtime;  
  6.     private String note;  
  7.     private User user;  
  8.     //getter、setter  
  9. }  
用戶信息類:

 

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public class User {  
  2.     private int id;  
  3.     private String username;  
  4.     private int sex;  
  5.     private Date birthday;  
  6.     private String address;  
  7.     //getter、setter  
  8. }  
再就是我們Mapper映射文件離間對resultMap的定義:

 

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. <pre code_snippet_id="2062392" snippet_file_name="blog_20161220_3_5346738" name="code" class="html"><resultMap type="com.ssm.mybatis.po.Orders" id="selectOrderUserLazyLoading">  
  2.         <!-- 配置映射的訂單信息 -->    
  3.         <id column="id" property="id"/>  
  4.         <result column="user_id" property="userId"/>  
  5.         <result column="number" property="number"/>  
  6.         <result column="createtime" property="createtime"/>  
  7.         <result column="note" property="note"/>  
  8.   
  9.         <!-- 配置映射的用戶信息 -->  
  10.         <association property="user" javaType="com.ssm.mybatis.po.User"   
  11.              select="com.ssm.mybatis.mapper.UserMapper.findUserById" column="user_id">             
  12.         </association>  
  13.     </resultMap></pre><br>  
  14. <br>  
  15. <pre></pre>  
  16. <p></p>  
  17. <pre></pre>  
  18. <p></p>  
  19. <pre></pre>  
  20. <pre></pre>  

在這里,注意我們的配置映射的映射信息里面有一個select屬性,這里實現的就是我們的延遲加載,后面就是我們定義的查詢用戶信息的Mapper的命名空間,也可以說是一個指向。

 

配置文件里面statement對resultMap的調用配置:
[html]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. <select id="selectOrderUserLazyLoading" resultMap="OrderUserLazyLoadingResultMap" >  
  2.         select * from orders  
  3. </select>  

接下來,我們定義一個mapper接口進行測試

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. public interface OrdersMapper{  
  2.     List<Orders> findOrderUserLazyLoading() throws Exception;  
  3. }  
測試:

 

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. @Test  
  2. public void selectOrderUserLazyLoading(){  
  3.     SqlSession session=sqlSessionFactory.openSession();  
  4.     OrdersMapperCustom ordersMapperCustomMapper=session.getMapper(OrdersMapperCustom.class);  
  5.     try {  
  6.         List<Orders> list=ordersMapperCustomMapper.findOrderUserLazyLoading();//查詢訂單信息  
  7.         if (list!=null) {//此處有斷點  
  8.                 System.out.println(list.get(0).getUser().getUsername());//查詢第一個訂單的用戶信息  
  9.         }  
  10.     } catch (Exception e) {//此處有斷電  
  11.         e.printStackTrace();  
  12.     }  
  13. }  
在上面的測試代碼里面,我們執行斷點查詢,分別在if和catch上打一個端點,看tomcat的日志信息

 

大家可以看到,當我們執行到第一個斷點的時候,這里mybatis只發出一條查詢訂單信息的sql去查詢所有的訂單信息。接下來,我們繼續往下走:

大家看到了,當我們執行到想要獲取第一個訂單的用戶信息時,它又發出了另一條根據id查詢用戶信息的sql,也就是說,當我們需要調用用戶信息的查詢方法時,它才會才會去執行查詢,這也就是我們所說的延遲加載,也叫做懶加載。大家可以很明顯的看到,在這里我們使用的association來實現的延遲加載,其使用collection也一樣,至於使用association和collection有什么區別呢,前面我們也介紹過,association是將關聯信息映射到一個pojo對象中,而collection是將關聯消息映射到list結合中,就這么簡單的理由

 

三、如何配置Mybatis延遲加載(懶加載)

      首先我們要知道,Mybatis默認是不支持執行延遲加載(懶加載)的,這需要我們手動去配置,去打開開關。而我們可以總結一下,但我們需要設置開啟二級緩存的時候,我們首先需要在Mybatis全局配置文件也就是我們的sqlMapConfig.xml中去設置開啟二級緩存,然后再去每個具體mapper映射文件中去確認本映射文件開啟二級緩存,也就是所有的全局性的功能或者是性能配置總閥門都在全局配置文件中的。所以我們是否開啟延遲加載的這一項功能也是在sqlMapConfig.xml中進行配置:

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到我的代碼片
  1. <settings>  
  2.    <setting name="lazyLoadingEnabled" value="true"/><!--延遲加載/懶加載-->  
  3.    <setting name="aggressiveLazyLoading" value="false"/><!--積極加載/預加載-->  
  4. </settings>  
然后如何在禁止懶加載的配置就不用再介紹了吧。

 

 

另外呢,通過看師哥師姐的博客以及外面人的介紹,mybatis的全局配置文件中的標簽是有先后順序的,按序分別是:properties、settings、typeAlliases、typeHandlers、objectFactory、plugins、environments、mappers。究竟是為什么呢,為了探究這個問題,我故意使用原生的mybatis(不與spring整合)配錯一個,結果真的如是個所說,報錯:

"元素類型為configuration的內容必須匹配(properties?,settings?,typeAliases?,typeHandlers?……"

相關知識:http://www.cnblogs.com/selene/p/4607004.html

 

四、總結:

       以上,就是我們mybatis實現延遲加載的一個簡單介紹,那現在回答剛開頭時問的問題,是所有的resultMap都能實驗延遲加載嗎?答案是:mybatis中能實現延時加載的是resultMap,彈死不是所有的resultMap都必須實現延時加載,我們利用的是resultMap里面的association和collection來實現的延遲加載。另外畢竟小編研究mybatis時間不長,難免有所疏漏,若有不足,還請各位指正,必及時修改。


免責聲明!

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



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