mybatis通过association和collection标签实现嵌套查询,支持延迟或立即加载;association用于一对一(如订单→用户),collection用于一对多(如用户→订单列表),均存在n+1问题;推荐大数据量时采用join+嵌套resultmap优化性能。

MyBatis 处理嵌套查询结果主要靠 resultMap 的 association(一对一)和 collection(一对多)标签,配合 select 属性实现延迟或立即加载。
用 association 映射一对一嵌套查询
适用于主表记录关联一个从表对象(如:订单 → 用户信息)。
- 在 resultMap 中用
<association property="user" column="user_id" select="selectUserById"></association> -
property指向 Java 对象的字段名(类型为 User) -
column是当前 SQL 查询结果中用于传参的列名(如 user_id) -
select引用另一个已定义的<select></select>语句 ID,该语句接收单个参数(默认按 column 值传入)
注意:这种写法会触发 N+1 查询(主查 1 次,每条记录再查 1 次),适合数据量小或需按需加载的场景。
用 collection 映射一对多嵌套查询
适用于主表一条记录对应多个从表记录(如:用户 → 订单列表)。
- 在 resultMap 中使用
<collection property="orders" column="id" select="selectOrdersByUserId"></collection> -
property字段类型应为List<order></order> - 被引用的
selectOrdersByUserId语句参数类型需与 column 值匹配(如 Long 或 Integer) - 同样存在 N+1 问题,但逻辑清晰、易于维护
用嵌套结果映射(join + resultmap)避免 N+1
通过 SQL JOIN 一次性查出所有字段,再用 resultMap 的嵌套结构做映射,性能更好。
- 主 resultMap 中用
<association property="user" javatype="User"></association>包裹子 resultMap - 子 resultMap 定义 user 表字段与 User 类属性的映射(用
<id></id>和<result></result>) - 一对多类似,用
<collection property="orders" oftype="Order"></collection>+ 内嵌 resultMap - 需确保 JOIN 后字段名不冲突,可用别名(如
u.id as user_id)并对应到子 resultMap 的 column
注意事项与建议
嵌套查询不是万能的,实际选型要看场景:
- 数据量小、调用频次低,用
select方式更直观 - 高并发或大数据量,优先用 JOIN + 嵌套 resultMap,或考虑分步查询 + 手动组装
- MyBatis 3.4+ 支持
fetchType="lazy"控制 association/collection 是否懒加载(需开启全局 lazyLoadingEnabled) - 若嵌套层级深,可配合
@SelectProvider或ResultHandler灵活处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











