架構實戰篇:使用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實戰聯盟”微信*公*眾*號哦~~~