"小崔,单表映射是幼儿园水平。生产环境全是关联查询,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。一个项目里两种风格并存,才是成熟的用法。"——白歌