延迟加载配置
延迟加载(Lazy Loading)在需要关联数据时才发起查询,减少不必要的数据库访问,优化查询性能。
全局配置
在 mybatis-config.xml 中开启:
XML
<settings>
<!-- 开启全局懒加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 关闭侵入式懒加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 指定触发加载的方法 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
| 配置项 | 默认值 | 说明 |
|---|---|---|
lazyLoadingEnabled | false | 是否开启全局懒加载 |
aggressiveLazyLoading | false (3.4.1+) | 侵入式加载:true 时调用任意方法触发全部加载 |
lazyLoadTriggerMethods | equals,clone,hashCode,toString | 触发加载的方法列表 |
局部控制:fetchType
在 association/collection 上单独配置覆盖全局设置:
XML
<resultMap id="orderResultMap" type="Order">
<id property="id" column="id"/>
<!-- 延迟加载用户信息 -->
<association property="user"
column="user_id"
javaType="User"
select="selectUser"
fetchType="lazy"/>
<!-- 立即加载订单项 -->
<collection property="items"
column="id"
ofType="OrderItem"
select="selectOrderItems"
fetchType="eager"/>
</resultMap>
| fetchType | 行为 |
|---|---|
lazy | 访问属性时才加载 |
eager | 查询主数据时同时加载 |
| 不配置 | 继承全局 lazyLoadingEnabled 行为 |
fetchType优先级高于全局配置,适合对特定关联做差异化加载策略。
lazyLoadTriggerMethods 详解
配置哪些方法调用会触发延迟加载:
XML
<!-- 仅调用 toString 时触发加载 -->
<setting name="lazyLoadTriggerMethods" value="toString"/>
<!-- 禁用所有方法触发(仅访问属性时加载) -->
<setting name="lazyLoadTriggerMethods" value=""/>
常见场景:
Java
Order order = mapper.selectOrder(1);
// aggressiveLazyLoading=false 时,以下不触发加载
order.getId();
order.getOrderNo();
// aggressiveLazyLoading=true 时,调用任意方法即触发
order.toString(); // 会触发 user 和 items 全部加载
// 仅访问属性时才加载(推荐模式)
User user = order.getUser(); // 此时触发 user 查询
aggressiveLazyLoading 行为差异
XML
<!-- aggressiveLazyLoading = true -->
<!-- 调用 order.toString() 会同时加载 user 和 items -->
<!-- aggressiveLazyLoading = false(推荐) -->
<!-- 仅访问 order.getUser() 时加载 user,访问 order.getItems() 时加载 items -->
3.4.1 版本后 aggressiveLazyLoading 默认值为 false,建议保持默认,避免不必要的数据加载。
延迟加载与序列化
延迟加载的代理对象在序列化时会触发加载:
Java
// Jackson/Fastjson 序列化时,会触发懒加载
String json = objectMapper.writeValueAsString(order);
// 结果:user 和 items 被加载并序列化
若需序列化但不触发加载:
Java
// 方案1:使用 DTO 手动转换
OrderDTO dto = new OrderDTO(order.getId(), order.getOrderNo());
// 方案2:配置 Jackson 忽略关联属性
@JsonIgnore
private User user;
完整配置示例
XML
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<resultMap id="blogResultMap" type="Blog">
<id property="id" column="id"/>
<result property="title" column="title"/>
<association property="author"
column="author_id"
javaType="Author"
select="selectAuthor"
fetchType="lazy"/>
<collection property="comments"
column="id"
ofType="Comment"
select="selectComments"
fetchType="lazy"/>
</resultMap>
要点总结
lazyLoadingEnabled=true开启全局延迟加载。aggressiveLazyLoading=false避免侵入式加载,推荐保持默认。fetchType可局部覆盖全局配置,实现差异化加载策略。lazyLoadTriggerMethods控制哪些方法调用触发加载。- 序列化会自动触发延迟加载,需使用 DTO 或 @JsonIgnore 避免。
- 合理配置延迟加载可显著减少不必要的数据库查询。
📝 发现内容有误?点击此处直接编辑