问题描述:
最近做项目时ORM框架用的mybatisPlus,分页插件也用的mybatisPlus自带的分页插件,业务是查询订单列表的同时把相关联的订单详情分页查询,每页展示十条数据,但前端请求时每页展示的条数却少了几条。但total数量正确,具体代码如下 :
@Data
@TableName("goods_order")
public class GoodsOrder {
@TableId
private String id;
private String shopId;
private String shopDeskId;
private String shopName;
private String openId;
private Integer mealsNumber;
private String shopIcon;
private BigDecimal totalPrice;
private Integer state;
private String phone;
@TableField(exist = false)
private List<GoodsOrderDetail> detailVOLists;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
@Null
private Date createdTime;
}
@Data
@TableName("goods_order_detail")
public class GoodsOrderDetail {
private String detailId;
private String orderId;
private String goodsId;
private String openId;
private String goodsTypeName;
private String goodsName;
private Integer goodsNumber;
private BigDecimal goodsPrice;
private String goodsIcon;
private String description;
private String prop1;
private String prop2;
private String hotSize;
private String remark;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdTime;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date updatedTime;
}
原因:
我们用的分页插件就是在我们的sql外加上具体数据库对应的分页方式(oracle用 RowNum,mysql 用limit),分页查询的时候把每一条多侧的数据当成一条分页数据,那这样可能查出来的五条都对应同一条主表数据,那这时候映射过后就只有一条数据。记住是先分页查询后映射数据结构。可能很多朋友再做一对多分页查询时和我一样
解决办法
既然我们知道问题的原因了,那我们怎么才能查到正确得一对多的分页结果呢?mybatis提供另一种方式,使用mybatis的子查询映射,xml文件和结果如下,问题完美解决。
<mapper namespace="com.*.mapper.GoodsOrderMapper">
<resultMap type="com.*.model.po.GoodsOrder" id="goodsOrderMap">
<id property="id" column="id"/>
<result property="shopId" column="shopId"/>
<result property="shopDeskId" column="shopDeskId"/>
<result property="shopName" column="shopName"/>
<result property="openId" column="openId"/>
<result property="mealsNumber" column="mealsNumber"/>
<result property="shopIcon" column="shopIcon"/>
<result property="totalPrice" column="totalPrice"/>
<result property="detail" column="detail"/>
<result property="state" column="state"/>
<result property="phone" column="phone"/>
<result property="createdTime" column="createdTime"/>
<collection property="detailVOLists" select="queryList" column="id" ofType="com.juyang.juyangshopbe.model.vo.GoodsOrderDetail">
</collection>
</resultMap>
<select id="selectOrderPageList" resultMap="goodsOrderMap">
SELECT go.id,go.shopId,go.shopName,go.openId,go.mealsNumber,go.shopIcon,go.totalPrice,go.createdTime from goods_order go
WHERE go.openId = #{openId} and go.state = #{code} ORDER BY go.createdTime DESC
</select>
<select id="queryList" resultType="com.*.model.vo.GoodsOrderDetail">
select * from goods_order_detail god where god.orderId =#{id}
</select>
第二种可能出现问题:
如果多表(包括了关系表)级联查询,主表和明细表的主键都是id的话,明细表的多条数据只能查询出来第一条/最后一条数据。这是因为主表和明细表的id字段名相同造成的。 问题的关键在于resultMap中如果不定义类似主键之类的能够区分每一条结果集的字段的话,会引起后面一条数据覆盖前面一条数据的现象。
比如这样的映射关系
解决方法一:
修改主表或者明细表的id名,保证不一致就行。
这是修改过后的映射关系
解决方法二:
查询结果起别名。