1. 程式人生 > >架構實戰篇:使用MyBatis延遲載入模式為資料庫減壓,附演示例項

架構實戰篇:使用MyBatis延遲載入模式為資料庫減壓,附演示例項

一.MyBatis延遲載入

1.延遲載入定義

resultMap可以實現高階對映(使用association、collection實現一對一及一對多對映),association、collection具備延遲載入功能。

  • 需求:如果查詢訂單並且關聯查詢使用者資訊。如果先查詢訂單資訊即可滿足要求,當我們需要查詢使用者資訊時再查下使用者資訊。把對使用者資訊的按需去查詢就是延遲載入。
  • 延遲載入:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高資料庫效能,因為查詢單表要比關聯查詢多張錶速度要快。

2.使用association實現延遲載入

1)需求

查詢訂單並且關聯查詢使用者資訊

2)mapper.xml

需要定義兩個mapper的方法對應的statement。

A、只查詢訂單資訊:

SELECT * FROM orders

在查詢訂單的statement中使用association去延遲載入(執行)下邊的statement(關聯查詢使用者資訊)。

<!-- 查詢訂單關聯查詢使用者 -->

 <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">

 SELECT * FROM orders </select>

B、關聯查詢使用者資訊

通過上邊查詢到的訂單資訊中user_id去關聯查詢使用者資訊

使用UserMapper.xml中的findUserById

 <select id="findUserById" parameterType="int" resultType="user">

 select * from user where id=#{value}

 </select>

上邊先去執行findOrdersUserLazyLoading,當需要去查詢使用者的時候再去執行fingUserById,通過resultMap的定義將延遲載入執行配置起來。

3)延遲載入resultMap

使用association中的select指定延遲載入去執行的statement的id。

<!-- 延遲載入的resultMap -->

 <resultMap type="joanna.yan.mybatis.entity.Orders" id="OrdersUserLazyLoadingResultMap">

 <!-- 1.對訂單資訊進行對映配置 -->

 <id column="id" property="id"/>

 <result column="user_id" property="userId"/>

 <result column="number" property="number"/>

 <result column="createtime" property="createtime"/>

 <result column="note" property="note"/>

 <!-- 2.實現對使用者資訊進行延遲載入 -->

 <!-- select:指定延遲載入需要執行的statement的id(是根據user_id查詢使用者資訊的statement) 

 要使用UserMapper.xml中findUserById完成根據使用者id(user_id)使用者資訊的查詢,

 如果findUserById不在本mapper中需要前邊加namespace。

 column:訂單資訊中關聯使用者資訊查詢的列,是user_id

 關聯查詢的sql理解為:

 SELECT orders.*,

 (SELECT username FROM USER WHERE orders.user_id = user.id)username,

 (SELECT sex FROM USER WHERE orders.user_id = user.id)sex

 FROM orders

 -->

 <association property="user" javaType="joanna.yan.mybatis.entity.User"

 select="joanna.yan.mybatis.mapper.UserMapper.findUserById" column="user_id">

 </association>

 </resultMap>

4)mapper.java

 //查詢訂單關聯查詢使用者,使用者資訊時延遲載入

 public List<Orders> findOrdersUserLazyLoading() throws Exception;

5)測試

A、測試思路

  • 執行上邊mapper方法(findOrdersUserLazyLoading),內部去呼叫joanna.yan.mybatis.mapper.OrdersCustomMapper中findOrdersUserLazyLoading只查詢orders資訊(單表)。
  • 在程式中去遍歷上一步驟查詢出的List<Orders>,當我們呼叫Orders中的getUser()時,開始進行延遲載入。
  • 延遲載入,去呼叫UserMapper.xml中findUserById這個方法獲取使用者資訊。

B、延遲載入配置

mybatis預設沒有開啟延遲載入,需要在SqlMapConfig.xml中setting配置。

在mybatis核心配置檔案中配置:lazyLoadingEnabled、aggressiveLazyLoading

 

阿里Java架構師分享:MyBatis延遲載入與查詢快取,附演示例項

在SqlMapConfig.xml中配置:

<!-- 全域性配置引數,需要時再設定 -->

 <settings>

 <!-- 開啟延遲載入的開關 -->

 <setting name="lazyLoadingEnabled" value="true"/>

 <!-- 將積極載入改為消極載入即按需要載入 -->

 <setting name="aggressiveLazyLoading" value="false"/>

 </settings>

C、測試程式碼

 @Test public void findOrdersUserLazyLoadingTest() throws Exception{

 SqlSession sqlSession=sqlSessionFactory.openSession();

 OrdersCustomMapper ordersCustomMapper=sqlSession.getMapper(OrdersCustomMapper.class);

 List<Orders> list=ordersCustomMapper.findOrdersUserLazyLoading(); for (Orders orders : list) { //執行getUser()去查詢使用者資訊,這裡實現按需載入

 User user=orders.getUser();

 System.out.println(user);

 }

 sqlSession.close();

 }

6)延遲載入思考

不使用mybatis提供的association及collection中的延遲載入功能,如何實現延遲載入?

定義兩個mapper方法如下:

1)查詢訂單列表

2)根據使用者id查詢使用者資訊

實現思路:先去查詢第一個mapper方法,獲取訂單資訊列表

在測試程式中,按需去呼叫第二個mapper方法去查詢使用者資訊。

總之,使用延遲載入方法,先去查詢簡單的sql(最好單表,也可以關聯查詢),再去按需要載入關聯查詢的其它資訊。

 

更多精彩內容可以關注“IT實戰聯盟”微信*公*眾*號哦~~~