首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis 延遲加載機制深度解析:association 與 collection 的按需查詢策略

     編輯:Java 綜合教學

MyBatis 延遲加載機制深度解析:association 與 collection 的按需查詢策略

MyBatis 的高級映射支援 <association> (一對一) 與 <collection> (一對多) 實現關聯對象映射。其核心優化特性——延遲加載,能顯著提升查詢效能,避免不必要的關聯表連接。

核心原理

延遲加載 = 先查主表,用到關聯對象時再發起關聯查詢。

  • 立即加載 (預設): 一次性執行多表 JOIN 或巢狀查詢,獲取完整對象圖。
  • 延遲加載: 主對象查詢返回後,關聯屬性持有代理對象;僅當調用 getter 方法時,才觸發關聯 SQL 執行。

適用場景與收益

場景立即加載痛點延遲加載優勢
列表頁僅顯示主表字段浪費資源查詢關聯表單表查詢,極快響應
關聯數據量大、查詢複雜JOIN 導致 Cartesian Product 膨脹按需拆分,減輕數據庫壓力
部分業務不需要關聯數據強制加載無用數據零開銷,真正按需

配置啟用 (核心配置文件)

<settings>
  <!-- 全局開啟延遲加載 -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!-- 積極延遲加載:調用任意方法觸發 (預設 false,僅 getter 觸發) -->
  <setting name="aggressiveLazyLoading" value="false"/>
</settings>

映射文件配置範例

<resultMap id="userMap" type="User">
  <id property="id" column="user_id"/>
  <result property="name" column="user_name"/>
  
  <!-- 一對一:訂單資訊 -->
  <association property="order" javaType="Order" 
    select="selectOrderByUserId" column="user_id" fetchType="lazy"/>
  
  <!-- 一對多:地址列表 -->
  <collection property="addresses" ofType="Address"
    select="selectAddressByUserId" column="user_id" fetchType="lazy"/>
</resultMap>

<select id="selectUser" resultMap="userMap">
  SELECT * FROM users WHERE id = #{id}
</select>

<select id="selectOrderByUserId" resultType="Order">
  SELECT * FROM orders WHERE user_id = #{user_id}
</select>

<select id="selectAddressByUserId" resultType="Address">
  SELECT * FROM addresses WHERE user_id = #{user_id}
</select>

關鍵屬性解析

  • select:關聯查詢的 statement ID
  • column:主查詢結果中作為參數傳遞給關聯查詢的列名
  • fetchType:lazy (延遲) / eager (立即),覆蓋全局設定
  • javaType / ofType:關聯對象類型

底層實現機制

  1. MyBatis 使用 CGLIB 或 Javassist 為關聯屬性生成代理對象。
  2. 代理攔截 getter 調用,檢查目標對象是否已加載。
  3. 未加載時,執行 select 指定的 SQL,將結果設置到真實對象,移除代理。
  4. 後續調用直接訪問真實對象。

常見坑與避雷指南

  • 序列化問題: 代理對象序列化可能失效,跨網絡傳輸前建議手動觸發加載或關閉延遲加載。
  • N+1 問題: 列表查詢 + 循環遍歷調用關聯 getter → 執行 N 次關聯查詢。解決:批量預加載或改用 JOIN。
  • 事務邊界: 延遲加載 SQL 需在同一 SqlSession/事務中執行,否則會報 no session 錯誤。
  • toString()/equals()/hashCode(): 若這些方法訪問關聯屬性,會意外觸發加載。建議 DTO 不重寫或排除關聯字段。

效能調優建議

  1. 列表查詢默認關閉延遲加載,改用 fetchType="eager" 或 ResultMap 合併查詢。
  2. 詳情頁、單對象查詢開啟延遲加載,減少無效關聯查詢。
  3. 監控 SQL 執行日誌,識別 N+1 模式並優化。

延遲加載是把雙刃劍:用對是效能倍增器,用錯是資料庫殺手。理解其代理機制與觸發條件,才能駕馭這項強大特性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved