前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pagehelper分页查询明明下一页没有数据了却还是返回了数据

pagehelper分页查询明明下一页没有数据了却还是返回了数据

作者头像
CBeann
发布2023-12-25 19:23:11
2420
发布2023-12-25 19:23:11
举报
文章被收录于专栏:CBeann的博客CBeann的博客

场景复现

数据库初始化有9条记录。当我通过分页插件去查询数据库时,查询第2页,每页10条记录时,查询的结果竟然有9条数据。结果显然不合理,因为我查询第2页,按照逻辑应该查询第11-20条记录,因此不存在,所以返回为空,但是现在却返回9条记录。

疑问如下:

  • 为什么返回数据???
  • 为什么返回9条数据???

解决办法

代码语言:javascript
复制
pagehelper:
#  helperDialect: mysql
  reasonable: false   # 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据

源码分析

源码跟踪

直接定位到PageInterceptor的intercept方法(为什么直接定位到这?

代码语言:javascript
复制
@Override
    public Object intercept(Invocation invocation) throws Throwable {
        try {
        
          
            //省略内容,省略内容,省略内容
 
            List resultList;
            //步骤1:调用方法判断是否需要进行分页,如果不需要,直接返回结果
            if (!dialect.skip(ms, parameter, rowBounds)) {
                //判断是否需要进行 count 查询
                if (dialect.beforeCount(ms, parameter, rowBounds)) {
                    //步骤2:查询总条数
                    Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);
                    //处理查询总数,返回 true 时继续分页查询,false 时直接返回
                    //步骤3:保存总条数
                    if (!dialect.afterCount(count, parameter, rowBounds)) {
                        //当查询总数为 0 时,直接返回空的结果
                        return dialect.afterPage(new ArrayList(), parameter, rowBounds);
                    }
                }
               //步骤4:执行分页查询
                resultList = ExecutorUtil.pageQuery(dialect, executor,
                        ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
            } else {
                //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
                resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
            }
            //步骤5:封装结果
            return dialect.afterPage(resultList, parameter, rowBounds);
        } finally {
            if(dialect != null){
                dialect.afterAll();
            }
        }
    }

我们看步骤3,保存总条数,总条数会保存到ThreadLocal的Page对象中,如图代码所示

代码语言:javascript
复制
//AbstractHelperDialect的afterCount方法
public boolean afterCount(long count, Object parameterObject, RowBounds rowBounds) {
        Page page = getLocalPage();
        //(重点,重点,重点)把count保存到page对象中
        page.setTotal(count);
        if (rowBounds instanceof PageRowBounds) {
            ((PageRowBounds) rowBounds).setTotal(count);
        }
        //pageSize < 0 的时候,不执行分页查询
        //pageSize = 0 的时候,还需要执行后续查询,但是不会分页
        if (page.getPageSize() < 0) {
            return false;
        }
        return count > ((page.getPageNum() - 1) * page.getPageSize());
    }

重点来了,我们跟进Page的setTotal方法

代码语言:javascript
复制
//Page###setTotal
public void setTotal(long total) {
        this.total = total;
        if (total == -1) {
            pages = 1;
            return;
        }
        if (pageSize > 0) {
            pages = (int) (total / pageSize + ((total % pageSize == 0) ? 0 : 1));
        } else {
            pages = 0;
        }
        //分页合理化,针对不合理的页码自动处理
        if ((reasonable != null && reasonable) && pageNum > pages) {
            if(pages!=0){
                //把pageNum设置为最后一页,震惊
                //把pageNum设置为最后一页,震惊
                //把pageNum设置为最后一页,震惊
                pageNum = pages;
            }
            calculateStartAndEndRow();
        }
    }

问题解析

为什么返回数据???

因为我查询的页数(pageNum = 2)大于总页数(pages = 1),因此把pages赋值给pageNum,查询最后一页肯定有数据===!

为什么返回9条数据???

因为我查询的页数(pageNum = 2)大于总页数(pages = 1),因此把pages赋值给pageNum,查询最后一页根据分析就是9条===!

参考

MyBatis的分页原理 pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-12-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景复现
  • 解决办法
  • 源码分析
    • 源码跟踪
      • 问题解析
        • 为什么返回数据???
        • 为什么返回9条数据???
    • 参考
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档