MyBatis一对一关联查询主要有嵌套结果和嵌套查询两种方式:前者通过JOIN一次查出全部字段并用association映射,执行1条SQL;后者先查主表再调用select属性指定的子查询查关联对象,执行N+1条SQL,支持延迟加载。

MyBatis 实现一对一关联查询主要有两种方式:嵌套结果(resultMap 嵌套映射)和嵌套查询(select 关联子查询)。二者核心区别在于 SQL 执行次数和数据组装时机——前者一次 SQL 查询 + 结果集手动映射,后者是主查 + 一次额外 select 查询,适合延迟加载或复用已有语句。
嵌套结果:用 resultMap 的 association 标签一次性映射
适用于主表与关联表能通过 JOIN 一次查出全部字段的场景。关键在定义好主 resultMap,并在其中用 <association></association> 指定关联对象及其映射规则。
- SQL 中使用 LEFT JOIN 关联从表,确保主表每条记录对应从表至多一条记录
- 在主 resultMap 中,用
property指定 Java 对象的属性名(如user),javaType指明类型(如User.class) -
<association></association>内部可嵌套另一个 resultMap,也可直接用column和property映射字段(推荐用嵌套 resultMap 提高可读性和复用性)
示例片段:
嵌套查询:用 association 的 select 属性触发二次查询
适合不想写 JOIN、需要复用已有查询语句、或希望按需加载(配合 lazyLoadingEnabled)的场景。MyBatis 会先执行主 SQL,再对每条结果调用指定的 select 语句查关联对象。
立即学习“Java免费学习笔记(深入)”;
- 主 resultMap 中的
<association></association>不写内部映射,而是设置select属性指向另一个<select></select>的 id - 用
column指定传递给子查询的参数列(如user_id),支持多列传参:column="{id=user_id, status=order_status}" - 被调用的 select 必须返回单个对象(结果集只有一行),否则 MyBatis 只取第一行,其余丢弃
- 开启懒加载时,该查询默认延迟执行;若关闭懒加载,则仍是一次性查完(N+1 问题依然存在)
示例片段:
column="user_id"/>
怎么选?关键看业务和性能要求
嵌套结果更高效(单 SQL),但字段命名易冲突,JOIN 条件复杂时 SQL 可维护性下降;嵌套查询逻辑清晰、解耦强,但有 N+1 风险,大量数据时性能明显变差。
- 数据量小、关联简单、对性能敏感 → 优先用嵌套结果
- 需要复用用户查询、或关联对象可能为空且不总需要加载 → 嵌套查询 + 懒加载
- MyBatis 3.4+ 支持
fetchType="lazy"写在 association 上,可覆盖全局懒加载配置 - 注意:嵌套查询中若 column 传的是 null,子查询不会执行(MyBatis 自动跳过),避免空指针异常
补充:自动映射 + 重命名也能简化嵌套结果
如果数据库字段命名规范(如 user_id, user_name),可开启 autoMappingBehavior="full",并用 columnPrefix 让 MyBatis 自动识别前缀字段:
columnPrefix="user_"/>
此时只要 SQL 返回字段带 user_id、user_name 等,MyBatis 就自动映射到 User 对象属性,无需显式写每个 <result></result>。


















