得嘞,分页插件PageHelper返回记录总数total竟然出错了!

京东云开发者
• 阅读 173

问题描述 分页返回的记录总数total和每页数量pageSize一致,数据库统计的数量大于当前返回的总记录数total,以下是相关代码

问题分析 sql错误导致返回信息有误? 检查结果:经过数据执行日志中生成的sql,sql正常并且数据总条数也正确

PageHelper使用方式错误,导致数据错误 检查结果:通过与项目中其他地方使用记录的对比,使用方式正确

返回结果后有中间处理导致总数减少 检查结果:网上有人遇到 对返回结果有类型转化导致total错误的情况, 以此类推,发现当前代码虽没有对返回结果进行类型转换但是对mapper返回的结果更换了实例对象然后将更换后的对象包装,

进一步查看包装成PageInfo时源码并没有关于total参数的处理,

PageInfo构造方法

public class PageInfo extends PageSerializable { /**

  • 包装Page对象

  • @param list page结果

  • @param navigatePages 页码数量

  • / public PageInfo(List list, int navigatePages) { super(list); if (list instanceof Page) {

      Page page = (Page) list;
      this.pageNum = page.getPageNum();
      this.pageSize = page.getPageSize();
    
      this.pages = page.getPages();
      this.size = page.size();
      //由于结果是>startRow的,所以实际的需要+1
      if (this.size == 0) {
          this.startRow = 0;
          this.endRow = 0;
      } else {
          this.startRow = page.getStartRow() + 1;
          //计算实际的endRow(最后一页的时候特殊)
          this.endRow = this.startRow - 1 + this.size;
      }

    } else if (list instanceof Collection) {

      this.pageNum = 1;
      this.pageSize = list.size();
    
      this.pages = this.pageSize > 0 ? 1 : 0;
      this.size = list.size();
      this.startRow = 0;
      this.endRow = list.size() > 0 ? list.size() - 1 : 0;

    } if (list instanceof Collection) {

      this.navigatePages = navigatePages;
      //计算导航页
      calcNavigatepageNums();
      //计算前后页,第一页,最后一页
      calcPage();
      //判断页面边界
      judgePageBoudary();

    } } } 继续查看父类PageSerializable,发现有关于total参数的处理,即mapper返回的list不是Page的实例时total会被设置为返回list的size大小

PageSerializable构造方法

public PageSerializable(List list) { this.list = list; if(list instanceof Page){ this.total = ((Page)list).getTotal(); } else { this.total = list.size(); } } 进一步debug,发现返回list确实不是Page类的实例,故推断出这一结果是由于对mapper返回list结果更换了实例对象导致的,

再次确认mapper返回结果,是Page的实例

解决方案 使用mapper返回的对象直接构造PageInfo对象,并在此基础上获取分页信息

更正的代码如下:

最佳实践 在使用 PageInfo pageInfo = new PageInfo<>(T); 构造PageInfo时直接使用mapper 返回对象,不要进行类型转换或转存等操作,以免丢失数据。

点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
sql的left join 、right join 、inner join之间的区别
sql的leftjoin、rightjoin、innerjoin之间的区别  leftjoin(左联接)返回包括左表中的所有记录和右表中联结字段相等的记录   rightjoin(右联接)返回包括右表中的所有记录和左表中联结字段相等的记录  innerjoin(等值连接)只返回两个表中联结字段相等的行举例如下: 
Wesley13 Wesley13
3年前
MySQL日志体系详解
前言日志是MySQL数据库的重要组成部分。日志文件中记录着MySQL数据库运行期间发生的变化;也就是说用来记录MySQL数据库的客户端连接状况、SQL语句的执行情况和错误信息等。当数据库遭到意外的损坏时,可以通过日志查看文件出错的原因,并且可以通过日志文件进行数据恢复。MySQL的日志体系有如下几种分类:1.错误日志2.查询日志
Stella981 Stella981
3年前
Spotlight on MySQL 参数详解
!(https://oscimg.oschina.net/oscnet/1eb23b1eb1612a58b59cdd6d0e2927e38cc.png) 1、Sessios会话TotalUsers:总用户数前连接到MySQL服务器的用户会话总数ActiveUsers:活跃用户此控件表示连接到当前正在执行SQL语句或其他数据库
Stella981 Stella981
3年前
Prometheus监控学习笔记之PromQL简单示例
0x00简单的时间序列选择返回度量指标http_requests_total的所有时间序列样本数据:http_requests_total返回度量指标名称为http_requests_total,标签分别是job"apiserver",handler"/api/comments"
Wesley13 Wesley13
3年前
mysql分页(ajax)
分页有多种方式,mysql的limit是个不错的选择,通过ajax实现异步刷新,将当前页数和每页数量传入后台即可1\.首先后台要拿到总记录数和所需显示数据列表,所以要分别写两个sql方法我这里是通过spring的注解方式写的sql,其它方法原理是一样的!复制代码(https://static.oschina.net/uploads/
Stella981 Stella981
3年前
PageImpl在springboot中的JSON序列化问题
在restapi中使用 org.springframework.data.domain.PageImpl 返回分页数据,有出现一些问题,问题以及解决方式如下:_(1) 返回的结果在springboot1.x 和springboot2.x中不一致_例如以下API@RestControllerpublicclas
Wesley13 Wesley13
3年前
MySQL IN语法注意事项一则
最近发现mysql中,Int型字段的默认值会直接影响IN语法的查询。如test表有个字段uid为int类型,默认值如果允许NULL,则下面的代码统计会不正确。//返回110条记录SELECTcount(1)FROMtest//若返回2条数据SELECT
Wesley13 Wesley13
3年前
JOIN关联表中ON,WHERE后面跟条件的区别
SQL中on条件与where条件的区别      数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。     在使用leftjion时,on和where条件的区别如下:1、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。2、where条件是
研发日常踩坑-Mysql分页数据重复 | 京东云技术团队
踩坑描述:写分页查询接口,orderby和limit混用的时候,出现了排序的混乱情况在进行第N页查询时,出现与第一前面页码的数据一样的记录。问题在MySQL中分页查询,我们经常会用limit,如:limit(0,20)表示查询第一页的20条数据,limit
小万哥 小万哥
11个月前
MySQL 数据库操作指南:LIMIT,OFFSET 和 JOIN 的使用
限制结果您可以通过使用"LIMIT"语句来限制查询返回的记录数量。以下是一个示例,获取您自己的Python服务器中"customers"表中的前5条记录:pythonimportmysql.connectormydbmysql.connector.conn