大家好,我是欧阳方超,微信公众号同名。
1 概述
在实际开发中我们经常遇到这样的场景,SQL查询结果中主表字段存在重复,因为它关联了多条子表数据,我们希望在Java端把这些重复的主表字段合并成一个对象,同时把对应的不重复的子表数据放到一个List集合中。这种一对多的映射关系是MyBatis-Plus(Mybatis)中非常典型的场景。本文将讲述如何在MyBatis-Plus的XML配置中实现这一功能。
2 场景描述
重复字段与一对多映射。假设有这样两个表,orders(订单表),存储订单信息,order_items(订单明细表),存储订单对应的商品明细。一条订单可能对应多条订单明细,因此SQL查询时,订单信息回重复出现多次,导致查询结果中主表字段(订单)重复,子表字段(商品明细)不同。
order_id | order_name | item_id | item_name |
---|---|---|---|
1 | 订单A | 101 | 苹果 |
1 | 订单A | 102 | 香蕉 |
12 | 订单B | 103 | 橙子 |
希望在Java程序中得到这样的东西:
一个订单对象Order,包含订单id和名称;
订单对象中有一个items属性,是一个List,包含所有该订单的商品明细。
3 解决方案核心思路
在SQL层面,使用join查询主表和子表,返回多行数据,主表字段重复。
在MyBatis XML中,使用resultMap定义映射规则,利用collection标签实现一对多关系,将子表数据映射成List集合。
MyBatis会根据主键自动合并重复的主表对象,避免重复创建,子表数据放入结合。
4 实现方式
4.1 定义Java实体类
public class Order {
private Long orderId;
private String orderName;
private List<OrderItem> items; // 一对多关联集合
// getter和setter省略
}
public class OrderItem {
private Long itemId;
private String itemName;
// getter和setter省略
}
4.2 编写Mapper XML
<resultMap id="OrderResultMap" type="Order">
<!-- 主表主键 -->
<id property="orderId" column="order_id"/>
<result property="orderName" column="order_name"/>
<!-- 一对多集合映射 -->
<collection property="items" ofType="OrderItem">
<id property="itemId" column="item_id"/>
<result property="itemName" column="item_name"/>
</collection>
</resultMap>
<select id="selectOrdersWithItems" resultMap="OrderResultMap">
SELECT o.order_id, o.order_name, i.item_id, i.item_name
FROM orders o
LEFT JOIN order_items i ON o.order_id = i.order_id
</select>
4.3 Mapper接口方法
List<Order> selectOrdersWithItems();
调用该方法即可获得订单列表,每个订单对象的items属性是对应的商品明细集合。
5 现象与原理
SQL返回多行,主表字段重复,子表字段不同。MyBatis根据id指定的主键字段,自动合并主表对象,避免重复创建。将对应的子表数据映射为子对象,放入主对象的集合属性中。Java程序中得到结构清晰的一对多对象模型,方便业务处理。
6 总结
通过resultMap和collection标签,可以轻松实现SQL查询中重复字段的合并和一对多数据的List映射。这种方式不仅代码简洁,且符合面向对象设计,极大提升开发效率和代码维可维护性。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。