mybatis延迟加载需精准配置:全局开启lazyloadingenabled=true且关闭aggressivelazyloading=false,关联映射中显式设fetchtype="lazy",实体类不可为final、getter不可重写、sqlsession须保持开启,并避免n+1查询。

MyBatis 延迟加载不是“开了就快”,而是要配得准、用得对。核心在于让关联数据只在真正需要时才查,避免主查询拖着几十条无关记录一起加载。
全局开关必须打开且配对
延迟加载默认是关闭的,必须显式启用两组关键配置:
- lazyLoadingEnabled=true:这是总闸门,不设为 true,所有局部配置都无效
- aggressiveLazyLoading=false:防止调用 toString()、equals() 等通用方法时误触发全部关联加载(否则 user.toString() 就可能把订单、地址、头像全拉一遍)
这两项需写在 mybatis-config.xml 的
关联映射里明确标注 lazy
光开全局不够,每个具体关联关系还得告诉 MyBatis:“这个我想要懒着点”。常见写法:
- 一对一:
<association property="profile" javatype="Profile" select="selectProfile" fetchtype="lazy"></association> - 一对多:
<collection property="orders" oftype="Order" select="selectOrdersByUserId" column="id" fetchtype="lazy"></collection>
注意:fetchType="lazy" 是局部覆盖全局的开关,比全局配置更优先;没写则按全局设置走。
确保代理能正常工作
MyBatis 靠动态代理实现延迟,有三个硬性前提:
- 被关联的实体类不能是 final(否则无法生成子类代理)
- 关联属性的 getter 方法不能被重写或屏蔽(代理靠拦截它触发查询)
- 执行 getter 时,SqlSession 必须仍处于开启状态(事务未提交/未关闭,否则会报 “No session” 异常)
避开 N+1 查询陷阱
延迟加载虽好,但若在循环中反复调用 getter,就会变成 N+1 查询(查 1 次主表 + N 次关联表)。优化建议:
- 批量场景下,改用 join 查询 + resultMap 手动映射,一次 SQL 拉全量
- 或用 分批预加载:先查出所有主 ID 列表,再用
IN一次性查关联数据,手动组装 - 日志里留意是否出现大量重复的 select 语句,那是典型信号
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











