news 2026/6/15 16:43:26

Spring Boot 使用 PageHelper 分页异常:排序引发的“隐形坑”全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 使用 PageHelper 分页异常:排序引发的“隐形坑”全解析

做Spring Boot项目开发的小伙伴,大概率都用过PageHelper做分页查询——毕竟它简洁高效,一行代码就能实现分页,之前项目里一直用得顺风顺水,从没出过错。

可就在昨天,分页突然“罢工”了,排查了大半天才找到根源,今天就把这个踩坑经历分享出来,帮大家避开这个隐形陷阱!

报错效果和核心代码如下(大家可以对照自己的项目排查):

【核心代码】:就是最常规的PageHelper分页操作,仅新增了排序逻辑,代码如下:

一步步排查,锁定排序这个“罪魁祸首”

比较其他业务发现,只多了个排序操作,所以尝试去掉排序——奇迹发生了,分页总数恢复正常,total能正确获取到,分页功能也完全正常。这就基本确定:异常就是排序操作引发的

通过Debug跟踪代码执行过程,重点查看分页插件的执行逻辑。发现了核心问题:新增排序后,分页插件并没有执行“查询总数”的SQL语句(也就是count查询)。

具体表现为:Debug到分页插件的核心逻辑时,负责查询总数的那一行代码(PageHelper内部的count查询逻辑)始终没有执行,直接跳过,导致total无法获取,最终异常。如图所示

深挖源码,找到底层原因:查阅了PageHelper的源码,重点分析了orderBy方法和beforeCount方法的执行逻辑。如图所示


最终发现:PageHelper的orderBy方法,在执行时会自动创建一个Page对象,而这个自动创建的Page对象,会导致PageHelper内部的beforeCount方法返回false—分页插件就会跳过count查询,自然就无法获取到分页总数了。

为什么排序会导致分页总数获取失败?

很多小伙伴可能还是有疑问:排序和分页总数,看似毫无关联,为什么会相互影响?

其实核心原因在于PageHelper的Page对象构建机制——PageHelper的分页功能,本质上是通过构建Page对象来实现的,而Page对象的构建有两种常见的方式,这也是本次异常的关键:

  • 方式一:使用PageHelper.startPage(pageNum, pageSize)方法,手动开启分页,这种方式会主动构建一个“分页Page对象”,同时默认执行count查询,获取分页总数;

  • 方式二:使用PageRowBounds对象,通过参数传递分页参数(pageNum、pageSize),这种方式也会触发分页,在拦截器中隐士构建Page对象。

而我们本次项目中,使用的是PageRowBounds方式实现分页,但新增的PageHelper.orderBy方法,有一个“隐形操作”:它会优先创建一个“不分页的Page对象”,这个自动创建的Page对象,会让PageRowBounds构建Page逻辑失效。

解决方案,一次性搞定

通过这次踩坑,我们不仅找到了异常的根源,更掌握了PageHelper分页的核心细节,这里给大家整理了避坑要点和具体解决方案,以后遇到类似问题,直接对照解决即可:

1.核心避坑点:使用PageRowBounds方式分页时,禁止使用PageHelper.orderBy方法——orderBy会自动创建不分页的Page对象,让PageRowBounds的分页配置失效,导致count查询失效、总数异常。

2.正确排序方式(两种可选):

① 放弃PageRowBounds,改用PageHelper.startPage方法分页,同时在startPage之后、查询之前执行orderBy排序,示例代码:

// 正确写法:startPage + orderBy PageHelper.startPage(pageNum, pageSize); PageHelper.orderBy("create_time desc");

② 保留PageRowBounds分页,将排序逻辑写入Mapper接口的SQL语句中(推荐,更高效、更稳定),示例代码:

<select> // Mapper接口SQL(新增order by) select * from user where status = 1 order by create_time desc; </select>
// 代码中仅保留分页,无需额外排序 PageRowBounds pageRowBounds = new PageRowBounds(pageNum, pageSize); List<User> userList = userMapper.selectUserList(pageRowBounds);

最后总结

其实这次异常,本质上是对PageHelper的底层逻辑了解不够深入——我们只知道orderBy能实现排序,却不知道它背后会自动创建Page对象,进而影响分页逻辑。很多技术踩坑,看似诡异,实则都是“细节疏忽”导致的。这里也补充几个关键注意事项,帮大家进一步避坑:

  • 尽量避免混用PageHelper的多种分页方式(startPage和PageRowBounds不要同时使用);

  • 使用orderBy方法时,务必确认当前的分页方式,避免触发“自动创建不分页Page对象”的隐形逻辑;

希望这篇解析,能帮大家避开这个PageHelper的隐形陷阱,以后做分页+排序时,少走弯路、提高开发效率。如果大家还有其他PageHelper的使用问题,也可以在评论区交流,一起避坑、一起进步!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 13:39:25

6款智能论文辅助工具因其改写能力和团队协作优势,登上高效学术推荐榜

学术写作领域现有多款智能辅助工具整合了文本生成与查重降重功能&#xff0c;依托先进的自然语言处理算法实现论文结构设计、语言润色及原创性检测&#xff0c;能有效支持学位论文创作和学术报告撰写等需求。需要强调的是&#xff0c;这类技术工具应当定位为研究效率的辅助手段…

作者头像 李华
网站建设 2026/6/15 13:15:17

华为OD技术面真题 - 计算机网络相关 - 4

文章目录简单介绍一下SYN FloodSYN Flood的常见形式如何缓解SYN FLood介绍一下UDP Flood如何缓解UDP Flood简单说说中间人攻击简单介绍一下SYN Flood SYN Flood 是互联网上最原始、最经典的 DDoS&#xff08;Distributed Denial of Service&#xff0c;分布式拒绝服务&#xf…

作者头像 李华
网站建设 2026/6/15 12:41:43

细胞电生理仿真软件:GENESIS_(5).编写和运行GENESIS脚本

编写和运行GENESIS脚本 1. GENESIS脚本的基本结构 在GENESIS中&#xff0c;脚本是用于定义和控制仿真的主要工具。这些脚本通常以.g或.gs为扩展名&#xff0c;使用的是GENESIS脚本语言&#xff08;GSL&#xff09;。GSL是一种类似于C语言的脚本语言&#xff0c;用于定义细胞、通…

作者头像 李华
网站建设 2026/6/15 11:34:47

欧氏内积(Euclidean Inner Product)

欧氏内积&#xff08;Euclidean Inner Product&#xff09;是n维欧几里得空间&#xff08;ℝ&#x1d45b;&#xff09;中定义的一种基础运算&#xff0c;通常称为点积或数量积。它将两个向量映射为一个标量&#xff0c;计算规则为对应分量乘积之和&#xff0c;即⟨&#x1d46…

作者头像 李华
网站建设 2026/6/15 12:41:28

【计算机网络 | 第二篇】三种交换方式和互联网的核心部分

文章目录核心部分的组成与特性分组交换与路由器的转发机制1. 路由器的处理过程2. 动态路径选择网络核心的两大功能&#xff1a;路由与转发三种交换方式的比较互联网的核心部分 &#xff1a;互联网的核心部分由大量网络和连接这些网络的路由器组成&#xff0c;其主要功能是为边缘…

作者头像 李华