• PageHelper关联查询 统计总数问题


    项目场景:

    业务:查询功能,需要关联多张表,为一对多或多对多。
    需求:要求分页,分页统计总数。
    使用技术:Mybatis,PageHelper


    问题描述

    正常查询一张表的情况下,官方推荐

    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);
    List<User> list = userMapper.selectAll();
    //用PageInfo对结果进行包装
    PageInfo page = new PageInfo(list);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    但是这种方式实际上PageHelper会自动生成:

    select count(0) from (selectAll() sql语句) table_count
    
    • 1

    普通查询返回正常统计数量。一对多、多对多关联返回的count不一定正确


    原因分析:

    关联查询的结果是以最小单位为一条数据进行统计的。这里的最小单位举例:学生表和成绩表关联,一个学生有多个课程成绩,那么查询学生的成绩时,一位学生+一门课程的成绩就为最小单位。但有时候我们需要根据成绩搜索学生,但是需要了解有多少个学生。
    这个时候PageHelper就无法自动实现了,需要自定义count解决。


    解决方案:

    以下说明我的错误经历

    • 错误方式1:
    /**
     * 这里的getUserList_COUNT SQL模板是:
     * SELECT count(*) FROM (getUserList SQL语句) table_count
     * 返回值类型:Long
     */
    // false 表示不使用统计总数,自定义统计数量
    PageHelper.startPage(1, 10, false).doCount(() -> stopShipMapper.getUserList_COUNT(params));
    // params这里指的是自定义的参数对象,可有可无,业务需求而已
    List<User> userList = stopShipMapper.getUserList(params);
    PageInfo<User> info = new PageInfo<>(userList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    报错:在系统中发现了多个分页插件,请检查系统配置!
    网上多数介绍,通过@SpringBootApplication(exclude = PageHelperAutoConfiguration.class),但是分页会失效,然后还有说多了两次自定义配置。但是只进行了一次配置。不存在这个问题。
    查看源码得知如下:
    在这里插入图片描述

    原因:也就是说查询方法名不能后缀_COUNT,否则报异常。

    • 错误方式2:
      于是乎改了调用方法名:
    /**
     * 这里的getUserList_COUNT SQL模板是:
     * SELECT count(*) FROM (getUserList SQL语句) table_count
     * 返回值类型:Long
     */
    // false 表示不使用统计总数,自定义统计数量
    PageHelper.startPage(1, 10, false).doCount(() -> stopShipMapper.getUserListTotal(params));
    // params这里指的是自定义的参数对象,可有可无,业务需求而已
    List<User> userList = stopShipMapper.getUserList(params);
    PageInfo<User> info = new PageInfo<>(userList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    错误:谢天谢地,count统计正常,但是查询语句后面没有后缀limit,分页失效。

    原因:PageHelper分页有效的SQL为PageHelper.startPage后紧跟着的一条SQL。上述代码紧跟着的SQL是count,干扰了分页查询。

    • 错误方式3:
      然后进一步修改,得到如下代码
    /**
     * 这里的getUserList_COUNT SQL模板是:
     * SELECT count(*) FROM (getUserList SQL语句) table_count
     * 返回值类型:Long
     */
    // false 表示不使用统计总数,自定义统计数量
    PageHelper.startPage(1, 10, false);
    // params这里指的是自定义的参数对象,可有可无,业务需求而已
    List<User> userList = stopShipMapper.getUserList(params);
    PageHelper.count(() -> stopShipMapper.getUserListTotal(params))
    PageInfo<User> info = new PageInfo<>(userList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    错误:然后又错啦,报错说什么要求return long 实际 return null。

    猜测原因:可能使用的是两个不同的分页对象,所以第二次只统计了总数,没有检测到没有分页查询

    • 错误方式4:
      接下来再改,得到如下代码
    /**
     * 这里的getUserListTotal SQL模板是:
     * SELECT count(*) FROM (getUserList SQL语句) table_count
     * 返回值类型:Long
     */
    // false 表示不使用统计总数,自定义统计数量
    // false 表示不使用统计总数
    Page page = PageHelper.startPage(1, 10, false);
    // params这里指的是自定义的参数对象,可有可无,业务需求而已
    List<User> userList = stopShipMapper.getUserList(params);
    // 自定义统计数量
    page.doCount(()-> stopShipMapper.getUserListTotal(params));
    PageInfo<User> info = new PageInfo<>(userList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    错误:分页数据正常啦,但是统计count又成了-1。

    原因:doCount是一个回调自定义处理函数,并没有对page做处理,因此需要手动处理。

    • 错误方式5:
    /**
     * 这里的getUserListTotal SQL模板是:
     * SELECT count(*) FROM (getUserList SQL语句) table_count
     * 返回值类型:Long
     */
    // false 表示不使用统计总数,自定义统计数量
    // false 表示不使用统计总数
    Page page = PageHelper.startPage(1, 10, false);
    // params这里指的是自定义的参数对象,可有可无,业务需求而已
    List<User> userList = stopShipMapper.getUserList(params);
    // 自定义统计数量
    page.doCount(() -> page.setTotal(stopShipMapper.getUserListTotal(params)));
    PageInfo<User> info = new PageInfo<>(userList);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    经过验证,最后一种方式也是有问题的,此时既可以分页,也可以统计数量,但是分页的结果还是最小单元。建议使用方式2,SQL使用子查询来先分页后关联数据

  • 相关阅读:
    Gorm框架学习---CRUD接口之创建
    2021年度全球CSS报告新鲜出炉,JavaScript调查推迟到明年
    AM@幂级数性质@幂级数和函数求解
    Spring Security入门
    【PlasticSCM Could Edition】新版本云托管浅试 (与踩一些坑)
    在win10环境下安装python,配置python环境,执行python脚本
    数学基础之概率论1
    C语言问题,整数查找,输入一个整数N,再输入一个整数M,查找整数M在N中第一次出现的位置。
    MATLAB小技巧(21)矩阵分析--偏最小二乘回归
    ubuntu 安装腾达U9 无线网卡 驱动-纯搬运-实测有效
  • 原文地址:https://blog.csdn.net/qq_30385099/article/details/126949340