MyBatis一对多关联查询通过<collection>标签实现,推荐使用嵌套结果(JOIN)方式避免N+1问题,需正确配置property、ofType、column及SQL别名映射。

MyBatis 中一对多关联查询通过 <collection> 标签实现,核心是配置好主表与从表的映射关系、SQL 关联方式(嵌套查询 or 嵌套结果),以及 Java 对象的集合属性。
1. 明确实体类结构(含集合属性)
确保“一”的一方(如 Order)包含“多”的一方(如 List<OrderItem>)的集合字段,并提供 getter/setter:
public class Order {
private Long id;
private String orderNo;
private List<OrderItem> items; // 关键:必须有这个集合属性
// getter/setter...
}
public class OrderItem {
private Long id;
private Long orderId;
private String productName;
private Integer quantity;
// getter/setter...
}
2. XML 映射中正确使用 <collection> 标签
<collection> 必须嵌套在 <resultMap> 内,用于描述集合属性的映射。有两种主流用法:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
嵌套结果(推荐,单 SQL 查询):用
JOIN一次性查出主从数据,通过column和property绑定外键字段与集合属性
<resultMap id="OrderWithItemsResultMap" type="Order">
<id property="id" column="order_id"/>
<result property="orderNo" column="order_no"/>
<collection property="items"
ofType="OrderItem"
column="order_id"
javaType="ArrayList">
<id property="id" column="item_id"/>
<result property="productName" column="product_name"/>
<result property="quantity" column="quantity"/>
</collection>
</resultMap>
<select id="selectOrderWithItems" resultMap="OrderWithItemsResultMap">
SELECT
o.id AS order_id, o.order_no,
i.id AS item_id, i.product_name, i.quantity
FROM `order` o
LEFT JOIN order_item i ON o.id = i.order_id
WHERE o.id = #{id}
</select>
- 嵌套查询(N+1 问题需注意):先查主表,再根据主表字段调用另一个 SQL 查询从表
<resultMap id="OrderWithItemsBySelectResultMap" type="Order">
<id property="id" column="id"/>
<result property="orderNo" column="order_no"/>
<collection property="items"
select="selectOrderItemsByOrderId"
column="id"/>
</resultMap>
<select id="selectOrderWithItemsBySelect" resultMap="OrderWithItemsBySelectResultMap">
SELECT id, order_no FROM `order` WHERE id = #{id}
</select>
<select id="selectOrderItemsByOrderId" resultType="OrderItem">
SELECT id, product_name, quantity FROM order_item WHERE order_id = #{id}
</select>
3. 注意关键配置项
-
property:必须与实体类中集合字段名完全一致(如items) -
ofType:指定集合中每个元素的类型(如OrderItem),不可省略 -
javaType:可选,显式指定集合接口类型(如ArrayList),默认为List -
column:用于传递给嵌套查询的参数,或用于JOIN结果中识别归属关系的列名 - 嵌套结果时,SQL 的列别名要和
<collection>内的<result>的column匹配,避免字段覆盖或映射失败
4. 使用注解方式(@Results + @Collection)
如果不用 XML,可用注解等效实现嵌套结果映射:
立即学习“Java免费学习笔记(深入)”;
@Select("SELECT o.id, o.order_no, i.id AS item_id, i.product_name, i.quantity " +
"FROM `order` o LEFT JOIN order_item i ON o.id = i.order_id WHERE o.id = #{id}")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "orderNo", column = "order_no"),
@Collection(
property = "items",
column = "id",
javaType = ArrayList.class,
ofType = OrderItem.class,
many = @Many(select = "selectOrderItemsByOrderId") // 或用 nestedQuery
)
})
Order selectOrderWithItems(@Param("id") Long id);
不复杂但容易忽略的是 column 别名一致性、ofType 类型声明、以及嵌套查询时的 N+1 风险——生产环境优先用嵌套结果(JOIN)方式。

















