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

问题描述

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

问题分析

  1. sql错误导致返回信息有误?

    检查结果:经过数据执行日志中生成的sql,sql正常并且数据总条数也正确

  2. PageHelper使用方式错误,导致数据错误

    检查结果:通过与项目中其他地方使用记录的对比,使用方式正确

  3. 返回结果后有中间处理导致总数减少

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

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

    PageInfo<T>构造方法

    ini 复制代码
    public class PageInfo<T> extends PageSerializable<T> {
    /**
     * 包装Page对象
     *
     * @param list          page结果
     * @param navigatePages 页码数量
     */
    public PageInfo(List<T> 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构造方法

    ini 复制代码
    public PageSerializable(List<T> 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<T> pageInfo = new PageInfo<>(T); 构造PageInfo时直接使用mapper 返回对象,不要进行类型转换或转存等操作,以免丢失数据。

相关推荐
岁岁岁平安1 小时前
Redis基础学习(五大值数据类型的常用操作命令)
数据库·redis·学习·redis list·redis hash·redis set·redis string
小光学长3 小时前
基于vue框架的防疫科普网站0838x(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库
极限实验室3 小时前
使用 Docker Compose 简化 INFINI Console 与 Easysearch 环境搭建
数据库·docker·devops
飞翔的佩奇3 小时前
Java项目:基于SSM框架实现的旅游协会管理系统【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·mysql·毕业设计·ssm·旅游·jsp
float_六七5 小时前
SQL六大核心类别全解析
数据库·sql·oracle
Code季风7 小时前
将 gRPC 服务注册到 Consul:从配置到服务发现的完整实践(上)
数据库·微服务·go·json·服务发现·consul
Boilermaker19927 小时前
【Java EE】SpringIoC
前端·数据库·spring
霸王龙的小胳膊7 小时前
泛微虚拟视图-数据虚拟化集成
数据库
灵犀学长7 小时前
解锁Spring Boot多项目共享Redis:优雅Key命名结构指南
数据库·redis
轩情吖8 小时前
Qt的信号与槽(二)
数据库·c++·qt·信号·connect·信号槽·