查詢訂單列表,訂單詳情(商品明細)非必須即時展示。若一次性 JOIN 兩表查詢,數據量大時極其消耗資源。延遲加載允許先查訂單,用戶點擊展開時再按需查詢詳情,實現「按需加載、分散壓力」。
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
lazyLoadingEnabled=true:全局啟用延遲加載。aggressiveLazyLoading=false:關鍵設置!true 時調用任意 getter 會觸發所有延遲屬性加載;false 時僅調用具體延遲屬性的 getter 才觸發加載(推薦)。<!-- 只查訂單主表 -->
<select id="findOrders" resultMap="orderResultMap">
SELECT * FROM orders
</select>
<!-- 按訂單 ID 查詳情 -->
<select id="findDetailsByOrderId" resultType="OrderDetailCustom">
SELECT * FROM orderdetail WHERE orders_id = #{orderId}
</select>
<resultMap id="orderResultMap" type="OrdersCustom">
<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"/>
<!-- 延遲加載詳情列表 -->
<collection property="orderDetails"
column="id"
ofType="OrderDetailCustom"
select="com.mapper.OrderDetailMapper.findDetailsByOrderId">
</collection>
</resultMap>
關鍵屬性解析:
property:實體類中對應的集合屬性名(List)。orderDetails column:主查詢結果中作為參數傳遞的列(訂單id)。ofType:集合泛型類型(一對多用ofType)。select:具體加載 SQL 的 Mapper 方法全限定名。
public class OrdersCustom extends Orders {
private List orderDetails; // 延遲加載屬性
// getter/setter
}
public class OrderDetailCustom extends OrderDetail {
private ItemsCustom items; // 可再嵌套一對一
// getter/setter
}
@Test
public void testLazyLoading() {
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List orders = mapper.findOrders(); // 斷點 1
// 此時控制台只打印「SELECT * FROM orders」
// 未執行任何 findDetailsByOrderId 查詢
System.out.println(orders); // 斷點 2:僅觸發 toString(),不調用 orderDetails getter
// 真正訪問詳情時才觸發查詢
for (OrdersCustom order : orders) {
List details = order.getOrderDetails(); // 此處發起 SQL
System.out.println(details);
}
}

select * from orderdetail where orders_id in (...))。@JsonIgnore 標記延遲屬性。SqlSessionFactory 共享連接或手動管理事務。OrderDetailCustom.items 可再配置 <association select="..."/> 實現多級延遲,屬性區別:一對一用 javaType,一對多用 ofType。MyBatis 通過 CGLIB 動態代理 生成實體類代理對象,攔截延遲屬性的 getter 調用,執行對應的 select 映射語句,將結果填充到屬性並返回。代理對象持有 SqlSession 引用,確保數據庫連接可用。
合理使用延遲加載,能在複雜對象圖查詢中實現「查詢拆分、按需執行、資源平滑」,是 MyBatis 應對高並發讀場景的利器。