项目场景:

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


问题描述

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

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

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

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

普通查询返回正常统计数量。一对多、多对多关联返回的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);

报错:在系统中发现了多个分页插件,请检查系统配置!
网上多数介绍,通过@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);

错误:谢天谢地,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);

错误:然后又错啦,报错说什么要求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);

错误:分页数据正常啦,但是统计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);

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

PageHelper关联查询 统计总数问题相关推荐

  1. es查询-统计总数以及深度分页

    一.查询总数 1.  ES 查询 hits 统计总数不准? 当我们使用 ES 的时候,有时会比较关心匹配到的文档总数是多少,所以在查询得到结果后会使用 hits.total.value 这个值作为匹配 ...

  2. Mybatisplus 分页查询时,禁止自动统计总数

    1.分页插件 使用 Mybatisplus 时 ,我们使用 PaginationInnerInterceptor 作为分页插件,它会帮助我们进行分页,查询总数. @Configuration @Map ...

  3. ABP 多模块关联查询、分组统计、列转行、Vue 复合表头动态列

    本文记录了一次使用abp Core5 ,vue 开发复杂报表的经历. 0.需求概述 业务需求是:统计一个化工厂车队形式记录数据中异常停车的报表,维度可以按照车俩.驾驶员两个维度进行统计,统计的元素有: ...

  4. 空值判断,双表关联数据统计查询

    SQL空值判断 oracle的是NVL(value,nullvalue) pgsql的是COALESCE(value,nullvalue) mysql的是IFNULL(value,nullvalue) ...

  5. Linq 多个DataTable表关联查询,实现考勤统计。

    最近在做考勤系统时,由于不同的分公司的数据源在不同的服务器上,关联查询比较麻烦,因此想到了用Linq实现关联查询. 思路:查询各个考勤信息的dataTable,然后用Linq实现DataTable的多 ...

  6. MySQL的多表关联查询

    一.多表关联查询 多表关联查询是使用一条SQL语句,将关联的多张表的数据查询出来. 1.1 交叉查询 交叉查询就是将多张表的数据没有条件地连接在一起进行展示. 1.1.1 语法 使用交叉查询类别和商品 ...

  7. oracle多表关联查询报表,oracle多表关联查询和子查询

    oracle多表关联查询和子查询 一.多表关联查询 例子: sql> create table student1 ( sid varchar(3), sname varchar(6), sage ...

  8. mysql join on 索引_连接查询,表关联查询join on,索引,触发器,视图

    一.连接查询 1.统计每一个部门的人数  "部门名,部门的人数" select department,count(eid) from employee group by depar ...

  9. Hibernate关联查询

    本文由广州疯狂软件java培训分享: 很多人认为hibernate一旦涉及到多张表查询就很不方便,只能通过原声sql解决,其实不然,hql语句其实已经比较强大了,基本涵盖了sql的60%的功能.我认为 ...

最新文章

  1. Leetcode: Populating Next Right Pointers in Each Node II
  2. 第四次Scrum编码冲刺
  3. php缓存accestoken_PHP获取微信access_token并缓存和自动更新
  4. [攻防世界 pwn]——Mary_Morton
  5. CString原理介绍
  6. 11.14 模拟:总结
  7. Redis:Big Key问题
  8. 我国企业对开源社区的贡献度_开源对企业有利的6个理由
  9. django进阶05中间件
  10. ubuntu 14.04 下 安装samba 及SSH 服务端的方法
  11. 2018-06-13 pymssql 访问 SQL Server 2017 或 pyodbc 访问支持 ODBC 的数据库
  12. 操作系统实验报告一 进程调度
  13. 如何让win7像win10一样漂亮-win7美化
  14. pmos低电平驱动_MOS管驱动电路详解
  15. 抽象类是不是必须要有抽象方法
  16. python短信验证码登录_Python实现短信验证
  17. 如何使单片机复位可靠,单片机复位电路?
  18. 微信小程序获取当前所在城市(地区定位与切换)
  19. win10计算机出现位置不可用desktop不可用,桌面只有此电脑几个图标,其它桌面图标都没有了
  20. java 调用 默认打印机 打印小票

热门文章

  1. 选择数字IC行业,就一定要读研吗?
  2. Python学习手册--第二部分(数据类型)
  3. 多元统计分析最短距离法_多元统计分析第10讲(聚类分析:动态聚类)
  4. 服务器盘符修改不了怎么办,服务器怎么修改盘符
  5. x265-1.7版本-encoder/slicetype.cpp注释
  6. 准时下班系列_Access合集之第2集—三种方案批量上传图片到数据库,你会几种?
  7. 2022 年工业工程、人工智能、计算机和应用科学前沿国际会议RTIACA2022征稿通知
  8. h5前端调用android拍照功能,H5调用Android拍照和摄像以及选取相册
  9. 社交圈子挖掘的一种快速的方法--label propagation
  10. 电视服务器媒体流中断是什么意思,视频流媒体服务器稳定吗?出现播放中断问题怎么办?...