SSM框架系列: (一) Mybatis之延遲載入
延遲載入定義:
百度釋義: 延遲載入(lazy load)是(也稱為懶載入),延遲載入機制是為了避免一些無謂的效能開銷而提出來的,所謂延遲載入就是當在真正需要資料的時候,才真正執行資料載入操作。
理解: Mybatis中, 延遲載入是 物件實體成員屬性詳情 載入的延遲.
〇. 前提:
為說明延遲載入, 先給出如下實體模型, 訂單實體 (Order) 中包含基本屬性 (id, name, time) 和兩個成員屬性 (Product實體, Customer實體) ;
一. Mybatis載入方式分為三種, 分別是:
1. 直接載入: 即使用實體的任何資訊時,載入全部資訊, 如下圖:
2. 侵入式延遲載入: 即需要使用延遲載入屬性詳情時, 將該物件的所有延遲載入實體屬性一次性載入, 如圖:
3. 深度延遲載入: 即真正的按需載入, 只加載真正需要使用的延遲載入項屬性, 如圖:
二. 清楚延遲載入的分類後, 來看Mybatis中各種延遲載入策略的配置:
1. 直接載入: 當不進行任何延遲載入配置時, 即為直接載入:
a. 方式1: 使用select語句一次加載出所有屬性, 再使用resultMap進行相應對映 (註解方式使用@Results);
b. 方式2: 使用select簡單查詢, 再根據查詢結果進行級聯查詢 (xml方式使用association和collection, 註解方式使用@One和@Many), 該種方式僅查詢Order基本屬性時, 會立即載入級聯載入的屬性, log記錄如下 (查詢基本屬性, 導致全部載入):
2. 侵入式延遲載入: xml配置 (註解方式比較特殊, 請看第4條分講):
即在Mybatis核心配置檔案中增加設定標籤如下, 再使用級聯查詢, 即實現了侵入式延遲載入:
<settings> <!--開啟延遲載入--> <setting name="lazyLoadingEnabled" value="true"/> <!--開啟浸入式延遲載入--> <setting name="aggressiveLazyLoading" value="true"/> </settings>
但是, 此時若查詢兩個實體屬性中的任意一個時, 會導致另一個實體屬性也被載入, 這也是侵入式載入的特點: " 所有延遲載入屬性合為一體 ", log下圖 (實際未使用3所載入的內容):
3. 深度延遲載入: xml配置 (註解方式比較特殊, 請看第4條分講):
即在Mybatis核心配置檔案中增加設定標籤如下, 再使用級聯查詢, 即實現了深度延遲載入:
<settings>
<!--開啟延遲載入-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--關閉浸入式延遲載入開關, 即進行深度延遲載入-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
此時, 但給我們查詢Order的其中一個實體成員屬性時, 另一個實體成員屬性不會被載入, 即實現了深度延遲載入, log日誌如下效果:
4. Myabtis 中的註解配置: 還支援註解配置查詢語句, 其中延遲載入的配置時通過在@One或者@ many標籤中配置 fetchType = FetchType.LAZY 屬性實現, 其作用時替代Mybatis核心配置檔案中的懶載入配置, 所以和 2/3 中的註解配置是替換關係, 而不是依賴關係:
配置舉例如下:
@Select("select * from orders")
@Results({
@Result(id = true,property = "id",column = "id"),
@Result(property = "orderNum",column = "orderNum"),
@Result(property = "orderTime",column = "orderTime"),
@Result(property = "peopleCount",column = "peopleCount"),
@Result(property = "orderDesc",column = "orderDesc"),
@Result(property = "payType",column = "payType"),
@Result(property = "orderStatus",column = "orderStatus"),
@Result(property = "productId",column = "productId"),
@Result(property = "product",column = "productId",javaType = Product.class,
one = @One(select = "com.wen.dao.IProductDao.findProductById",fetchType = FetchType.LAZY)),
@Result(property = "product2",column = "peopleCount",javaType = Product.class,
one = @One(select = "com.wen.dao.IProductDao.findProductById",fetchType = FetchType.LAZY))
})
List<Order> findAllOrder();
此時會有人好奇, 註解方式中並沒有侵入式延遲和深度延遲的選項, 經博主實測, Mybatis的註解方式配置延遲載入預設就是 深度延遲載入;
三. 延遲載入策略也的優劣和選擇:
1. 優缺點:
優點:
先查詢基本屬性, 加快了響應速度, 當需要時才去載入實體成員屬性內容
缺點:
增加了查詢次數, 當大量查詢時, 降低了資料庫的效能
2. 選擇:
不使用場景: 深度理解延遲載入的優缺點後, 便可以根據需求進行選擇, 當查詢資料量大, 且頻繁查詢成員實體屬性時, 使用延遲載入是不合適的, 吃此時會增加資料庫的查詢次數, 從而導致資料庫效能消耗;
使用場景: 而當查詢資料量小, 或者查詢時幾乎很少但是可能會用到成員實體屬性時, 選用延遲載入可以避免多表聯查或者大量級聯查詢, 屬於一種資料庫程式碼級別的的效能優化;
轉載請標明出處: 划船一哥