news 2026/4/23 8:20:20

MyBatis-Plus 分页插件失效?深扒 PageHelper 与 MP 冲突的底层源码,教你避开“假分页”陷阱

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MyBatis-Plus 分页插件失效?深扒 PageHelper 与 MP 冲突的底层源码,教你避开“假分页”陷阱

🚨 前言:凌晨 1 点的 OOM 惊魂

场景还原:生产环境某个列表接口突然响应巨慢,紧接着应用抛出OOM (Out Of Memory)崩溃。
排查日志发现,原本应该是分页查询的 SQL,竟然没有LIMIT语句!

-- 期望的 SQL (物理分页)SELECT*FROMuserWHEREstatus=1LIMIT0,10-- 实际执行的 SQL (全表扫描 + 内存分页)SELECT*FROMuserWHEREstatus=1

这就是典型的分页插件失效。如果表里有 100 万行数据,应用服务器的内存瞬间就会被撑爆。


⚔️ 一、 核心原理:MyBatis 的拦截器机制

要理解为什么失效,必须先懂 MyBatis 的插件原理。
MyBatis 允许我们在 SQL 执行的生命周期中进行拦截(Interceptor)。

  • PageHelper:通过PageInterceptor拦截Executor,检测ThreadLocal中是否有Page对象(PageHelper.startPage()),如果有,就改写 SQL。
  • MyBatis-Plus:通过MybatisPlusInterceptor拦截Executor,检测参数中是否有IPage接口的实现类,如果有,就改写 SQL 添加LIMIT

拦截器链示意图 (Mermaid):

1. Mapper 调用

执行最终 SQL

拦截器链 (责任链模式)

放行

放行

改写 SQL (LIMIT)

拦截器 A

拦截器 B

MP 分页拦截器

PageHelper 拦截器

应用代码

MyBatis 核心

数据库


💣 二、 事故现场:三种常见的“失效”姿势

1. 最低级错误:完全没配置拦截器 (MP 3.4.0+)

很多新手以为引入了mybatis-plus-boot-starter就万事大吉了。
错!在 MP 3.4.0 之后,必须显式配置MybatisPlusInterceptorBean,否则分页功能完全不生效。

错误代码:

// ControllerPage<User>page=newPage<>(1,10);userMapper.selectPage(page,null);// 结果:SQL 无 LIMIT,全表查询
2. 隐形冲突:PageHelper 抢戏

如果你的项目里既引入了pagehelper-spring-boot-starter,又想用 MP 的selectPage
PageHelper 的自动配置可能会干扰 MP,或者在同一个 ThreadLocal 里产生了脏数据。
虽然现在的版本兼容性好了很多,但混用依然是 Bug 的温床。

3. 参数传递错误

如果你在自定义 SQL 中使用分页:

// MapperList<User>selectUserList(Page<User>page,@Param("name")Stringname);

如果Page对象不是第一个参数,且没有正确处理,MP 的拦截器可能识别不到它,从而放弃改写 SQL。


🔍 三、 源码深扒:为什么配置了 Bean 还是没用?

假设你已经配置了MybatisPlusInterceptor,但依然失效。我们需要看源码。

打开MybatisPlusInterceptor.java,找到intercept方法:

@OverridepublicObjectintercept(Invocationinvocation)throwsThrowable{// 1. 获取所有内部拦截器 (如分页、乐观锁等)List<InnerInterceptor>interceptors=this.interceptors;// 2. 遍历拦截器for(InnerInterceptorinterceptor:interceptors){// 3. 调用 willDoQuery (关键点!)// 这里会判断是否需要进行分页处理if(!interceptor.willDoQuery(executor,ms,parameter,rowBounds,resultHandler,boundSql)){returninterceptor.beforeQuery(executor,ms,parameter,rowBounds,resultHandler,boundSql);}}// ...}

再看PaginationInnerInterceptor.java(分页拦截器核心):

@OverridepublicbooleanwillDoQuery(...){// 1. 获取参数中的 IPage 对象IPage<?>page=ParameterUtils.findPage(parameter).orElse(null);// 2. 如果参数里没找到 Page 对象,或者 Page.size < 0if(page==null||page.getSize()<0||!page.isSearchCount()){// 直接返回 true,不做处理 -> 导致 LIMIT 缺失!returntrue;}// ...}

结论:只要 MP 在参数列表里找不到IPage对象,它就当作普通查询处理,直接放行,导致“假分页”。


✅ 四、 终极解决方案

方案 1:标准配置 (必做)

在 Spring Boot 配置类中,必须注册MybatisPlusInterceptor,并添加PaginationInnerInterceptor

@ConfigurationpublicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();// 1. 添加分页拦截器// DbType.MYSQL 根据你的数据库类型选择,不要漏了!interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));// (可选) 如果有乐观锁等其他插件,也在这里添加// interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());returninterceptor;}}
方案 2:依赖隔离 (推荐)

如果新项目全面拥抱 MP,建议直接移除 PageHelper 依赖

方案 3:自定义 SQL 的规范写法

在 Mapper.xml 对应的 Interface 中,确保Page参数放在第一位,或者虽然不在第一位但 MP 能识别。

// ✅ 推荐写法:Page 放在第一个参数IPage<UserDto>selectCustomUsers(IPage<UserDto>page,@Param("status")Integerstatus);

📊 五、 性能自测:怎么确认分页生效了?

不要只看接口返回的数据条数!

  1. 开启 MP 的 SQL 打印
mybatis-plus:configuration:log-impl:org.apache.ibatis.logging.stdout.StdOutImpl
  1. 观察控制台
  • 正常:看到LIMIT ?, ?结尾的 SQL。
  • 异常:看到SELECT count(0)...查总数,但随后的查询语句没有LIMIT

🎯 总结

MyBatis-Plus 的分页插件失效,90% 都是因为配置缺失依赖冲突
“假分页”是生产环境的隐形杀手,它平时不报错,一到大促流量洪峰就 OOM。

Next Step:
赶紧去检查一下你的 Config 类,那个new MybatisPlusInterceptor()到底加了没?别等到报警电话响了才后悔!

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

来聊聊用西门子1200玩转液体混合控制的骚操作。这个项目最带劲的地方在于用仿真系统就能模拟真实产线的全套流程,省了买设备的钱还能随便折腾

液体混合装置plc控制系统 西门子1200仿真系统 采用博途V15编写&#xff0c;全自动仿真完成。 宝贝包含程序和画面。 实现要求:液体混合装置控制系统&#xff0c;由液面传感器SL1、SL2、SL3&#xff0c;液体A、B、C阀门与混合液阀门&#xff08;电磁阀YV1、YV2、YV3、YV4&#x…

作者头像 李华
网站建设 2026/4/17 23:56:54

Sonic数字人四川话模拟可行性分析:地域化应用新方向

Sonic数字人四川话模拟可行性分析&#xff1a;地域化应用新方向 在短视频与直播内容爆炸式增长的今天&#xff0c;观众对“真实感”和“亲近感”的追求已远超简单的视觉呈现。尤其是在西南地区&#xff0c;一句地道的“巴适得板”“要得嘛”&#xff0c;往往比标准普通话更能拉…

作者头像 李华
网站建设 2026/4/18 7:06:54

Confluence搭建Sonic内部Wiki协作平台

Confluence 搭建 Sonic 内部 Wiki 协作平台 在虚拟主播、在线教育和企业数字人宣传日益普及的今天&#xff0c;如何以低成本、高效率生成自然流畅的说话视频&#xff0c;已成为许多团队面临的核心挑战。传统方案依赖复杂的3D建模与动作捕捉系统&#xff0c;不仅周期长、门槛高&…

作者头像 李华
网站建设 2026/4/18 0:28:59

超导磁能储存系统的建模和仿真附Simulink仿真

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

作者头像 李华
网站建设 2026/4/18 20:30:03

vivado2025多节点通信网络拓扑设计完整指南

一文吃透vivado2025多节点通信网络设计&#xff1a;从AXI到NoC的实战全解你有没有遇到过这样的情况&#xff1f;FPGA系统越做越大&#xff0c;模块越来越多&#xff0c;原本清晰的信号连接图变成了“意大利面条”——满屏交叉、时序难调、资源抢夺严重。特别是当你试图把ADC采集…

作者头像 李华