"小崔,单表映射是幼儿园水平。生产环境全是关联查询,association 和collection 不通,你就写不出像样的DAO。"——白歌
本章定位
一句话:本章解决"如何将多表关联查询结果映射为嵌套对象结构、如何避免N+1 性能陷阱"的问题。
飞翔科技的ERP 系统需要展示"订单+用户+商品明细"的复杂页面,小崔一开始写了6 条单表查询,页面加载耗时8 秒。白歌一看日志:N+1 问题。大翔下了死命令:本周内重构所有关联查询,必须一条SQL 或延迟加载解决。这一章,小崔把MyBatis 的结果映射高级武器全部解锁。
学习路线图
学习顺序说明:
- 先深钻resultMap(resultMap 详解)→ 掌握所有子标签的语义和复用机制
- 再学一对一(association)→ 处理"订单属于一个用户"的对象嵌套
- 再学一对多(collection)→ 处理"一个部门有多个员工"的集合嵌套
- 再看鉴别器(discriminator)→ 处理"同一查询返回不同子类"的多态场景
- 最后攻性能(延迟加载 / N+1 查询问题)→ 掌握关联查询的性能边界和规避方案
文件关系说明
| 文件 | 一句话角色 |
|---|---|
resultMap 详解.md | 本章地基:系统讲解resultMap 的所有子标签(id/result/association/collection/discriminator)、继承复用(extends)和自动映射叠加 |
association.md | 一对一映射:将关联表的一行数据映射为当前对象的嵌套属性(如Order.user) |
collection.md | 一对多映射:将关联表的多行数据映射为当前对象的集合属性(如Dept.employees) |
discriminator.md | 多态鉴别:根据某列值决定使用哪个resultMap 子分支,实现"同表不同类"的映射 |
延迟加载.md | 性能优化开关:关联对象按需加载,配合aggressiveLazyLoading 和lazyLoadTriggerMethods 精细控制 |
N+1 查询问题.md | 性能避坑指南:分析N+1 成因,对比嵌套结果映射(一条SQL)和延迟加载(多条SQL 但按需)两种方案 |
知识图谱
核心概念关系:
resultMap是"总容器",id/result处理简单属性,association处理嵌套对象,collection处理嵌套集合,discriminator处理多态分支association和collection都有两种加载方式:- 嵌套查询(select):发另一条SQL,可配延迟加载,但滥用导致N+1
- 嵌套结果(resultMap):一条SQL JOIN 多表,用resultMap 分解列到不同对象,无N+1 风险
discriminator是"类型路由器",根据列值(如type=1走VIP 映射,type=2走普通映射)切换分支延迟加载是"性能缓冲垫":开启后,association/collection 的嵌套查询不会立即执行,直到真正访问属性N+1 问题是"性能红线":查询1 条主数据触发N 条关联查询,必须在架构层面规避
与下一章的衔接
本章学完后,小崔能用XML 处理复杂关联映射,但每个Mapper 都写XML 文件,项目里XML 越堆越多。白歌问:简单的CRUD 能不能不写XML?
下一章《MyBatis 注解开发》将解决:如何用 @Select、@Insert、@Update、@Delete 等注解直接在Mapper 接口上写SQL,实现零XML 的轻量级开发,以及注解与XML 的取舍策略。
"XML 适合复杂映射,注解适合简单CRUD。一个项目里两种风格并存,才是成熟的用法。"——白歌