Catalog
- MyBatis在两张表是一对多的情况下,进行分步查询,发现对查询出来的结果进行封装时没有将实体类的id进行赋值
- 1. 表结构
- 2. 场景
- 3. 实现方式
- 具体步骤
- 4 .测试
- 5. 解决方法
MyBatis在两张表是一对多的情况下,进行分步查询,发现对查询出来的结果进行封装时没有将实体类的id进行赋值
1. 表结构
大致了解一下即可,bug在后面…
-
订单表
CREATE TABLE `orders` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `number` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '订单号', `status` int NOT NULL DEFAULT '1' COMMENT '订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消 7退款', `user_id` bigint NOT NULL COMMENT '下单用户', `address_book_id` bigint NOT NULL COMMENT '地址id', `order_time` datetime NOT NULL COMMENT '下单时间', `checkout_time` datetime DEFAULT NULL COMMENT '结账时间', `pay_method` int NOT NULL DEFAULT '1' COMMENT '支付方式 1微信,2支付宝', `pay_status` tinyint NOT NULL DEFAULT '0' COMMENT '支付状态 0未支付 1已支付 2退款', `amount` decimal(10,2) NOT NULL COMMENT '实收金额', `remark` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '备注', `phone` varchar(11) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '手机号', `address` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '地址', `user_name` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '用户名称', `consignee` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '收货人', `cancel_reason` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '订单取消原因', `rejection_reason` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '订单拒绝原因', `cancel_time` datetime DEFAULT NULL COMMENT '订单取消时间', `estimated_delivery_time` datetime DEFAULT NULL COMMENT '预计送达时间', `delivery_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '配送状态 1立即送出 0选择具体时间', `delivery_time` datetime DEFAULT NULL COMMENT '送达时间', `pack_amount` int DEFAULT NULL COMMENT '打包费', `tableware_number` int DEFAULT NULL COMMENT '餐具数量', `tableware_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '餐具数量状态 1按餐量提供 0选择具体数量', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin COMMENT='订单表';
-
订单明细表
主要记录每个订单上,每一类商品的具体信息,一类商品占一条记录CREATE TABLE `order_detail` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '名字', `image` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '图片', `order_id` bigint NOT NULL COMMENT '订单id', `dish_id` bigint DEFAULT NULL COMMENT '菜品id', `setmeal_id` bigint DEFAULT NULL COMMENT '套餐id', `dish_flavor` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL COMMENT '口味', `number` int NOT NULL DEFAULT '1' COMMENT '数量', `amount` decimal(10,2) NOT NULL COMMENT '金额', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin COMMENT='订单明细表';
-
查询结果封装类
public class OrderVO implements Serializable { /** * 订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消 */ public static final Integer PENDING_PAYMENT = 1; public static final Integer TO_BE_CONFIRMED = 2; public static final Integer CONFIRMED = 3; public static final Integer DELIVERY_IN_PROGRESS = 4; public static final Integer COMPLETED = 5; public static final Integer CANCELLED = 6; /** * 支付状态 0未支付 1已支付 2退款 */ public static final Integer UN_PAID = 0; public static final Integer PAID = 1; public static final Integer REFUND = 2; private static final long serialVersionUID = 1L; private Long id; //订单号 private String number; //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消 7退款 private Integer status; //下单用户id private Long userId; //地址id private Long addressBookId; //下单时间 private LocalDateTime orderTime; //结账时间 private LocalDateTime checkoutTime; //支付方式 1微信,2支付宝 private Integer payMethod; //支付状态 0未支付 1已支付 2退款 private Integer payStatus; //实收金额 private BigDecimal amount; //备注 private String remark; //用户名 private String userName; //手机号 private String phone; //地址 private String address; //收货人 private String consignee; //订单取消原因 private String cancelReason; //订单拒绝原因 private String rejectionReason; //订单取消时间 private LocalDateTime cancelTime; //预计送达时间 private LocalDateTime estimatedDeliveryTime; //配送状态 1立即送出 0选择具体时间 private Integer deliveryStatus; //送达时间 private LocalDateTime deliveryTime; //打包费 private int packAmount; //餐具数量 private int tablewareNumber; //餐具数量状态 1按餐量提供 0选择具体数量 private Integer tablewareStatus; //订单菜品信息 private String orderDishes; //订单详情 private List<OrderDetail> orderDetailList; }
2. 场景
在实现苍穹外卖的查询历史订单这个接口时,发现前端需要返回的数据需要两张表联查,这两张表分别时订单表和订单明细表,订单表和订单明细表是一对多的关系,即一条订单记录可能对应多条订单明细记录,然后将结果进行封装。
这里考到考虑这两张表的冗余字段(即不同表之间相同的字段)比较多,对于查询出来的结果集封装赋值到Java实体类的时候,需要改很多别名,所以这里决定直接使用分步查询
- 根据用户id查询出所有的订单信息
- 根据订单id查询出所有的订单明细信息
3. 实现方式
这里考虑到业务层代码不具备复用性,即每个项目的业务逻辑基本都是不一样的,所以直接看mapper层的代码
具体步骤
- 先设计好结果集映射,即我们需要将查询出来的订单明细信息赋值到List这个集合里面,在springboot工程的配置文件中已经开启了驼峰命名映射,所以其它字段不需要再添加到中。
- 查询订单表
- 查询订单明细表(注意标签中column是“select="com.sky.mapper.OrderMapper.selectWithDetailTwo”执行这段查询语句的条件,即订单表的id)
<resultMap id="selectWithDetailResultMap" type="com.sky.vo.OrderVO" >
<collection property="orderDetailList"
ofType="com.sky.entity.OrderDetail"
select="com.sky.mapper.OrderMapper.selectWithDetailTwo"
column="id">
</collection>
</resultMap>
<select id="selectWithDetail"
resultType="com.sky.vo.OrderVO"
resultMap="selectWithDetailResultMap"
parameterType="com.sky.dto.OrdersPageQueryDTO"
>
select * from orders
<where>
<if test="userId != null ">
user_id = #{userId}
</if>
<if test="status != null ">
and status = #{status}
</if>
</where>
</select>
<select id="selectWithDetailTwo" resultType="orderDetail">
select * from order_detail where order_id = #{id}
</select>
4 .测试
使用swagger2测试的时候发现,每一条订单的id都是空的,但是实体类其它属性的值都赋上了,尽管已经开启了驼峰命名映射(字段名和实体类属性名的映射)。
5. 解决方法
目前由于本人还没有学习过Mybatis框架的源码,无法追溯到具体问题的源头,只有一个笨方法:直接标签中增加id的映射,如下
- 结果:订单的id成功赋值。