当前位置: 首页 > news >正文

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()到底加了没?别等到报警电话响了才后悔!

http://www.jsqmd.com/news/183228/

相关文章:

  • 【开题答辩全过程】以 基于python的阳泉房产推荐系统为例,包含答辩的问题和答案
  • DeepSeek 部署报错 “Connection refused“?Ollama 本地服务连接失败的 3 种终极解决方案
  • 采用SRF算法的分流有源滤波器【并联有源滤波器的仿真电路可降低谐波和无功功率】附Simulink仿真
  • 实用指南:AI RAG 向量数据库深度对比
  • 168_尚硅谷_二维数组介绍和入门
  • Sonic数字人四川话模拟可行性分析:地域化应用新方向
  • Node.js console.time轻松测函数耗时
  • VoxCPM-1.5-TTS-WEB-UI语音合成支持服务注册与发现机制
  • Mathtype授权一台机?我们的服务支持多实例运行
  • HTML表单提交数据?现在用API调用生成语音
  • 导师严选10个AI论文写作软件,助本科生轻松搞定毕业论文!
  • 军事模拟系统:指挥官训练中使用VoxCPM-1.5-TTS-WEB-UI生成敌情通报
  • 达姆施塔特工业大学发现:专家混合模型AI安全机制存在脆弱性
  • LabVIEW与VisionPro联调实战:工业视觉那些不能跳过的坑
  • uniapp+ssm中学生社团管理系统小程序
  • uniapp+ssm中学生社团管理系统小程序
  • 中科大联手字节跳动:用涂鸦就能编辑图片的神奇AI工具诞生了
  • 妇联组织用Sonic讲述三八红旗手先进事迹
  • uniapp+ssm医院预约挂号小程序
  • 超导磁能储存系统的建模和仿真附Simulink仿真
  • uniapp+ssm学校高校校园生活综合服务系统小程序
  • 政府信息公开:市民拨打热线听取VoxCPM-1.5-TTS-WEB-UI政策解读
  • 港大与Adobe联合推出突破性Self-E模型
  • 车间调度基于麻雀优化算法的车间调度附Matlab代码
  • 滑铁卢大学颠覆性发现:AI学习错误答案竟比学对答案更聪明!
  • uniapp+ssm志愿者活动报名服务小程序设计与开发
  • Springboot基于web的电影院售票系统的设计与实现_e509t(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • uniapp+ssm游戏账号租赁小程序
  • 工业级 AWS ECS Fargate 应用实战指南
  • Meta发布AI代码生成新突破:让机器自动写出超高性能计算内核