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;//下单用户idprivate Long userId;//地址idprivate 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成功赋值。