记一次MyBatis分页插件使用时遇到的问题

孤人 提交于 2020-05-03 17:40:22

问题描述

在使用 Mybatis-PageHelper 进行分页的时候,查询出来的结果集是一个嵌套的结果,此时发现查询出来的记录数与设置的 pagesize 明显不符合。

问题还原

我的 mapper 实现时这么写的 ,

  <resultMap id="myOrdersVo" type="com.cjervin.vo.MyOrdersVO">
    <id column="orderId" property="orderId"/>
    <result column="createdTime" property="createdTime"/>
    <result column="payMethod" property="payMethod"/>
    <result column="realPayAmount" property="realPayAmount"/>
    <result column="postAmount" property="postAmount"/>
    <result column="orderStatus" property="orderStatus"/>
    <result column="isComment" property="isComment"/>
    <collection property="subOrderItemList" ofType="com.cjervin.vo.MySubOrderItemVO">
      <result column="itemId" property="itemId"/>
      <result column="itemName" property="itemName"/>
      <result column="itemImg" property="itemImg"/>
      <result column="itemSpecName" property="itemSpecName"/>
      <result column="buyCounts" property="buyCounts"/>
      <result column="price" property="price"/>
    </collection>
  </resultMap>

  <select id="queryMyOrderList" parameterType="map" resultMap="myOrdersVo">
      SELECT
          o.id AS orderId,
          o.created_time AS createdTime,
          o.pay_method AS payMethod,
          o.real_pay_amount AS realPayAmount,
          o.post_amount AS postAmount,
          os.order_status AS orderStatus,
          o.is_comment AS isComment,
          oi.item_id AS itemId,
          oi.item_name AS itemName,
          oi.item_img AS itemImg,
          oi.item_spec_name AS itemSpecName,
          oi.buy_counts AS buyCounts,
          oi.price AS price
      FROM orders o
      LEFT JOIN order_status os ON o.id = os.order_id
      LEFT JOIN order_items oi ON o.id = oi.order_id
      WHERE o. user_id = #{paramMap.userId}
      AND o.is_delete = 0
      <if test="paramMap.orderStatus != null">
        AND os.order_status = #{paramMap.orderStatus}
      </if>
      ORDER BY o.updated_time ASC
  </select>

MyOrdersVO:

public class MyOrdersVO {

    private String orderId;
    private Date createdTime;
    private Integer payMethod;
    private Integer realPayAmount;
    private Integer postAmount;
    private Integer isComment;
    private Integer orderStatus;

    private List<MySubOrderItemVO> subOrderItemList;

MySubOrderItemVO:

public class MySubOrderItemVO {

    private String itemId;
    private String itemImg;
    private String itemName;
    private String itemSpecName;
    private Integer buyCounts;
    private Integer price;

可以看到,xml 里面配置的一个叫做 myOrdersVo 的 resultMap 下面还嵌套了一个collection子结果集。

servcice:

    @Override
    public PagedGridResult queryMyOrders(String userId, Integer orderStatus, Integer page, Integer pageSize) {
        Map<String,Object> map = new HashMap<>();
        map.put("userId",userId);
        if (orderStatus != null) {
            map.put("orderStatus", orderStatus);
        }
        PageHelper.startPage(page,pageSize);
        List<MyOrdersVO> orderList = ordersMapperCustom.queryMyOrderList(map);
        return setterPagedGrid(orderList,page);
    }
    public PagedGridResult setterPagedGrid(List<?> list, Integer page) {
        PageInfo<?> pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }

controller:

    @PostMapping("/query")
    public JSONResult query(@RequestParam("userId") String userId,@RequestParam("orderStatus")Integer orderStatus,
                            @RequestParam(value ="page",defaultValue = "1")Integer page,
                            @RequestParam(value ="pageSize",defaultValue = "10")Integer pageSize){

        PagedGridResult pagedGridResult = myOrderService.queryMyOrders(userId, orderStatus, page, pageSize);

        return JSONResult.ok(pagedGridResult);
    }

然后使用 postman 来测试,

我们看到返回的结果只有三条,与之前传进去的4明显有偏差,但是展开后如果按照子结果集的数量算的话是可以对上的

这与我们的期望不符,我们希望的是,父结果集可以展示4条!!

问题解决:

Mybatis-PageHelper 将代码托管在 github ,我们去看一眼是否有解决的办法,以下是截图:

分页插件不支持嵌套结果映射,那只能自己想办法了

既然一次 select 不行,那我们把嵌套的那部分抽取出来,查询两次应该可以解决问题

  <resultMap id="myOrdersVo" type="com.cjervin.vo.MyOrdersVO">
    <id column="orderId" property="orderId"/>
    <result column="createdTime" property="createdTime"/>
    <result column="payMethod" property="payMethod"/>
    <result column="realPayAmount" property="realPayAmount"/>
    <result column="postAmount" property="postAmount"/>
    <result column="orderStatus" property="orderStatus"/>
    <result column="isComment" property="isComment"/>
    <collection property="subOrderItemList" select="getSubItems" column="orderId" ofType="com.cjervin.vo.MySubOrderItemVO">
      <result column="itemId" property="itemId"/>
      <result column="itemName" property="itemName"/>
      <result column="itemImg" property="itemImg"/>
      <result column="itemSpecName" property="itemSpecName"/>
      <result column="buyCounts" property="buyCounts"/>
      <result column="price" property="price"/>
    </collection>
  </resultMap>

    <select id="getSubItems" parameterType="string" resultType="com.cjervin.vo.MySubOrderItemVO">
      select
        oi.item_id as itemId,
        oi.item_name as itemName,
        oi.item_img as itemImg,
        oi.item_spec_name as itemSpecName,
        oi.buy_counts as buyCounts,
        oi.price as price
      from order_items oi
      where oi.order_id = #{orderId}
    </select>

  <select id="queryMyOrderList" parameterType="map" resultMap="myOrdersVo">
      SELECT
          o.id AS orderId,
          o.created_time AS createdTime,
          o.pay_method AS payMethod,
          o.real_pay_amount AS realPayAmount,
          o.post_amount AS postAmount,
          os.order_status AS orderStatus,
          o.is_comment AS isComment
      FROM orders o
      LEFT JOIN order_status os ON o.id = os.order_id
      WHERE o. user_id = #{paramMap.userId}
      AND o.is_delete = 0
      <if test="paramMap.orderStatus != null">
        AND os.order_status = #{paramMap.orderStatus}
      </if>
      ORDER BY o.updated_time ASC
  </select>

我们同过 collection 标签 的 select 标签可以在一个查询里嵌套一次查询, 通过 collection 标签的 column 标签做一个值传递。可以解决上述问题,接着来测试一下:

问题解决!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!