mybatis plus IPage分页插件在连表查询中的问题

491 阅读1分钟

mybatis plus IPage分页插件在连表查询中的问题

  1. 先上代码

    1. java

      1. orderController

        @GetMapping("/order/testGetList")
        public Response<List<Order>> testGetList(@RequestParam(required = false) Integer type){
            List<Order> data =  orderService.listOderData(type);
            return Response.ok(data);
        }
        
      2. oderService

         List<Order> listOderData(Integer type);
        
      3. orderServiceImpl

          public List<Order> listOderData(Integer type) {
                PageQuery pageQuery = new PageQuery();
                pageQuery.setPageNumber(1);
                pageQuery.setPageSize(10);
                IPage iPage = PageUtil.toIPage(pageQuery);
                return baseMapper.listOderData(iPage,type);
            }
        
      4. oderDao

      List<Order> listOderData(@Param("iPage") IPage iPage, @Param("type") Integer type);
      
    2. xml

      <select id="listOderData" resultType="xxxxxx.model.Order">
              <choose>
              <!-- 当 type 等于 1 时,执行第一条 SQL 语句 -->
              <when test="type == 1">
                  select o1.id from `order` o1 join order_item o2 on o1.id = o2.`order` order by id desc
              </when>
              <!-- 当 type 等于 2 时,执行第二条 SQL 语句 -->
              <when test="type == 2">
                  select id from `order` order by id desc   limit 1, 2
              </when>
                  <otherwise>
                      select id from `order` order by id desc
                  </otherwise>
              </choose>
          </select>
      
  2. 执行结果

    1. type=1时候,

      1. 最终生成的sql

        select o1.id  from `order` o1 join order_item o2 on o1.id = o2.`order` order by id desc LIMIT 0,10
        
      2. 返回的数据-id都一样

        ==> Parameters: 
        <==    Columns: id
        <==        Row: 501761
        <==        Row: 501761
        <==        Row: 501761
        <==        Row: 501761
        <==        Row: 501761
        <==        Row: 501761
        <==        Row: 501760
        <==        Row: 501759
        <==        Row: 501759
        <==        Row: 501759
        <==      Total: 10
        
    2. type=2时候

      1. 最终生成的sql

        select id from `order` order by id desc limit 1, 2 
        
      2. 响应的数据

        ==> Parameters: 
        <==    Columns: id
        <==        Row: 501760
        <==        Row: 501759
        <==      Total: 2
        
    3. type=3时候

      1. 最终生成的sql

        select id from `order` order by id desc LIMIT 0,10 
        
      2. 响应的数据

        ==> Parameters: 
        <==    Columns: id
        <==        Row: 501761
        <==        Row: 501760
        <==        Row: 501759
        <==        Row: 501758
        <==        Row: 501757
        <==        Row: 501756
        <==        Row: 501755
        <==        Row: 501754
        <==        Row: 501753
        <==        Row: 501752
        <==      Total: 10
        

    结论:

    1. mybatis plus 的IPage 分页插件只是单纯的在SQL语句中拼接了 limit子句
    2. 在连表查询中,如果使用这个方法,有可能导致最终查询出来的分页数据是查询结果的笛卡尔积的数据的值,如上述订单场景查出来的都是同一个订单(id相同)的数据,很多情况下我们需要进行分页的数据是订单数据,而不是连表后的结果
    3. 可以使用GROUP BY 子表.id将冗余数据进行合并再LIMIT分页,但该方法,无法解决查询结果的数据量问题,可能有性能问题