MyBatis一对多关联查询核心是<collection>标签配置,支持嵌套Select(需防N+1)和嵌套ResultMap(推荐中等数据量),关键在于字段绑定、别名避免冲突、集合初始化及缓存优化。

一对多关联查询的核心配置方式
MyBatis 实现一对多(如“一个订单对应多个订单项”)主要靠 <resultMap> 中的 <collection> 标签。关键不是写 SQL 多复杂,而是让 MyBatis 知道:主对象(Order)和子集合(List<OrderItem>)如何按字段绑定、如何复用结果、是否需要延迟加载。
两种主流映射方式对比与选择
嵌套 Select 查询(N+1 问题需警惕)
在 Order 的 resultMap 中,为 items 字段配置 collection,select 指向另一个查询语句:
优点:逻辑清晰、SQL 职责分离;缺点:默认触发 N+1 查询——查 100 个订单,额外执行 100 次 item 查询。可通过 fetchType="lazy" 开启按需加载,或配合 @SelectProvider 动态控制。
嵌套 ResultMap(推荐用于中等数据量)
用一条 JOIN SQL 查出所有数据,再通过 <collection> 的 ofType 和 column 映射关系自动分组聚合:
<id property="id" column="order_id"/>
<result property="name" column="order_name"/>
<collection property="items" ofType="OrderItem"
column="order_id"
javaType="ArrayList">
<id property="id" column="item_id"/>
<result property="sku" column="item_sku"/>
</collection>
</resultMap>
注意:必须给 JOIN 字段起别名避免列名冲突(如 order.id → order_id,item.id → item_id),否则 MyBatis 无法区分主从字段。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
避免常见坑的实操建议
- 开启 autoMappingBehavior=FULL 或 PARTIAL,但 collection 内部字段仍需显式定义,autoMap 不生效
- 使用 <discriminator> 处理多态子类(如不同类型的订单项),避免硬编码 if-else
- 大数据量场景下,禁用嵌套 resultMap 的 JOIN 方式,改用分页 + 批量 in 查询(如先查 orderIds,再用
WHERE order_id IN (#{ids})一次查完所有 items) - 实体类中集合属性务必初始化(如
private List<OrderItem> items = new ArrayList<>();),否则空指针风险高
性能优化的关键点
真正影响性能的往往不是写法,而是数据规模与缓存策略:
立即学习“Java免费学习笔记(深入)”;
- 对高频读、低频改的关联数据,开启 二级缓存 并设置
flushCache="false"防止误刷 - 用 @Options(useCache = true) 显式启用缓存,尤其搭配嵌套 Select 时更有效
- JOIN 查询时加 ORDER BY order_id, item_id,帮助 MyBatis 更高效分组(内部基于 LinkedHashMap 顺序聚合)
- 必要时用 RowBounds 或 分页插件 对子集合做截断(如只取前 5 条明细),避免传输冗余数据

















