在resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。例如:我們查詢訂單並且關聯查詢用戶信息。如果先查詢訂單信息即可滿足要求,當我們需要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
延遲加載:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高 數據庫性能,因為查詢單表要比關聯查詢多張表速度要快。
如果我們查詢訂單信息並且關聯查詢用戶信息,在不需要查看用戶信息的情況下只需要查詢訂單信息,如果需要查看用戶信息在查詢用戶信息。
1、映射文件:
需要定義兩個mapper的方法對應的statement,一個用於簡單的查詢,另一個用於需要查詢時再查詢。
(1)、只查詢訂單信息
1 <select id="findOrderLazyLoad" resultMap="ordersUserResultMapLazyLoad"> 2 select * from 3 orders 4 </select>
(2)、關聯查詢用戶信息:
1 <select id="findUserLazyLoad" parameterType="int" resultType="user"> 2 select * from user where id = #{value} 3 </select>
上邊先去執行findOrderLazyLoad,當需要去查詢用戶的時候再去執行findUserLazyLoad,通過resultMap的定義將延遲加載執行配置起來。
1 <!-- 訂單查詢關聯用戶的resultMap,將整個查詢結果映射到orders中,延遲加載 --> 2 <resultMap type="com.luchao.mybatis.first.po.Orders" id="ordersUserResultMapLazyLoad"> 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 <!-- 實現對用戶信息進行延遲加載 select:指定延遲加載需要執行的statement的id(是根據user_id查詢用戶信息的statement) 9 要使用userMapper.xml中findUserById完成根據用戶id(user_id)用戶信息的查詢,如果findUserById不在本mapper中需要前邊加namespace 10 column:訂單信息中關聯用戶信息查詢的列,是user_id 關聯查詢的sql理解為: SELECT orders.*, (SELECT username 11 FROM USER WHERE orders.user_id = user.id)username, (SELECT sex FROM USER 12 WHERE orders.user_id = user.id)sex FROM orders --> 13 <association property="user" javaType="com.luchao.mybatis.first.po.User" 14 select="findUserLazyLoad" column="user_id"> 15 16 </association> 17 </resultMap>
select:指定延遲加載需要執行的statement的id(是根據user_id查詢用戶信息的statement),要使用userMapper.xml中findUserById完成根據用戶id(user_id)用戶信息的查詢,如果findUserById不在本mapper中需要前邊加namespace,column:訂單信息中關聯用戶信息查詢的列,是user_id。
關聯查詢的SQL語句可以理解為:
1 SELECT orders.*, 2 (SELECT username FROM USER WHERE orders.user_id = user.id)username, 3 (SELECT sex FROM USER WHERE orders.user_id = user.id)sex 4 FROM orders
2、Mapper接口:
1 //查詢訂單、訂單明細和用戶信息通過resultMap延遲加載 2 public List<Orders> findOrderLazyLoad() throws Exception;
3、延遲加載的配置:
mybatis默認沒有開啟延遲加載,需要在SqlMapConfig.xml中setting配置。在mybatis核心配置文件中配置:lazyLoadingEnabled、aggressiveLazyLoading
設置項
描述
允許值
默認值
lazyLoadingEnabled
全局性設置懶加載。如果設為‘false’,則所有相關聯的都會被初始化加載。
true | false
false
aggressiveLazyLoading
當設置為‘true’的時候,懶加載的對象可能被任何懶屬性全部加載。否則,每個屬性都按需加載。
true | false
true
在SqlMapConfig.xml中配置
1 <settings> 2 <!-- 打開延遲加載的開關 --> 3 <setting name="lazyLoadingEnabled" value="true" /> 4 <!-- 將積極加載改為消極加載即按需加載 --> 5 <setting name="aggressiveLazyLoading" value="false" /> 6 </settings>
4、測試:
1 public void findOrderLazyLoad() throws Exception { 2 // 獲取sqlSession對象 3 SqlSession sqlSession = sqlSessionFactory.openSession(); 4 // 創建OrderMapper對象,MyBatis自動生成mapper代理 5 OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); 6 // 調用orderMapper的方法,查詢訂單和用戶信息延遲加載 7 List<Orders> Orders = orderMapper.findOrderLazyLoad(); 8 for (Orders order : Orders) { 9 System.out.println(order.getUser()); 10 } 11 }
查詢結果:
1 DEBUG [main] - ==> Preparing: select * from orders 2 DEBUG [main] - ==> Parameters: 3 DEBUG [main] - <== Total: 3 4 DEBUG [main] - ==> Preparing: select * from user where id = ? 5 DEBUG [main] - ==> Parameters: 1(Integer) 6 DEBUG [main] - <== Total: 1 7 1-王五-2-null-null 8 1-王五-2-null-null 9 DEBUG [main] - ==> Preparing: select * from user where id = ? 10 DEBUG [main] - ==> Parameters: 10(Integer) 11 DEBUG [main] - <== Total: 1 12 10-張明明3-1-北京市-Thu Jul 10 00:00:00 CST 2014
可以看出先查詢orders表,然後在查看user的時候再查看user。
如果不使用mybatis提供的association及collection中的延遲加載功能,如何實現延遲加載??
實現方法如下:
定義兩個mapper方法:1、查詢訂單列表,2、根據用戶id查詢用戶信息
實現思路:
先去查詢第一個mapper方法,獲取訂單信息列表
在程序中(service),按需去調用第二個mapper方法去查詢用戶信息。
總之:使用延遲加載方法,先去查詢簡單的sql(最好單表,也可以關聯查詢),再去按需要加載關聯查詢的其它信息。
小結:
作用:當需要查詢關聯信息時再去數據庫查詢,默認不去關聯查詢,提高數據庫性能。只有使用resultMap支持延遲加載設置。
場合:當只有部分記錄需要關聯查詢其它信息時,此時可按需延遲加載,需要關聯查詢時再向數據庫發出sql,以提高數據庫性能。
當全部需要關聯查詢信息時,此時不用延遲加載,直接將關聯查詢信息全部返回即可,可使用resultType或resultMap完成映射。