MyBatis 的高級映射支援 <association> (一對一) 與 <collection> (一對多) 實現關聯對象映射。其核心優化特性——延遲加載,能顯著提升查詢效能,避免不必要的關聯表連接。
延遲加載 = 先查主表,用到關聯對象時再發起關聯查詢。
| 場景 | 立即加載痛點 | 延遲加載優勢 |
|---|---|---|
| 列表頁僅顯示主表字段 | 浪費資源查詢關聯表 | 單表查詢,極快響應 |
| 關聯數據量大、查詢複雜 | 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 IDcolumn:主查詢結果中作為參數傳遞給關聯查詢的列名fetchType:lazy (延遲) / eager (立即),覆蓋全局設定javaType / ofType:關聯對象類型select 指定的 SQL,將結果設置到真實對象,移除代理。no session 錯誤。fetchType="eager" 或 ResultMap 合併查詢。延遲加載是把雙刃劍:用對是效能倍增器,用錯是資料庫殺手。理解其代理機制與觸發條件,才能駕馭這項強大特性。