PageHelper分页的原理

PageHelper会通过修改SQL语句的方式,在SQL后面动态拼接上limit语句

流程

ThreadLocal 隔离线程数据

PageHelper 是一个基于 MyBatis 的 拦截器(Interceptor) 实现的分页插件。它的核心原理是在 MyBatis 执行 SQL 之前,动态修改 SQL 语句,加入数据库方言相关的分页语法(比如 MySQL 的 LIMIT)。

PageHelper.startPage() 会将分页参数封装成 Page 对象,存入当前线程的 ThreadLocal

实现线程隔离,多并发请求之间分页参数互不干扰。

MyBatis 拦截器捕获查询请求

PageInterceptor 通过 @Intercepts 注解拦截 Executor 的 query 方法。

Executor 是 MyBatis 的核心执行器接口,定义了所有 SQL 执行方法。

dialect.skip() 内部调用了 PageHelper.getLocalPage(),从 ThreadLocal 取分页参数

总数查询 + 分页数据查询

执行 COUNT 查询

改写 SQL(加 LIMIT)+ 执行分页查询

清理 ThreadLocal

PageHelper.startPage() 必须紧跟 Mapper 查询,拦截器只会在有分页参数的查询执行后 才会清理 ThreadLocal

如果查询没执行,或执行前就异常了,ThreadLocal 不会被清理

存储分页参数->拦截并改造 SQL->封装结果并清理现场

返回数据

ini 复制代码
PageHelper.startPage(1,10)
List<Dept> list=deptMapper.selectDept(name, status);

这里容易产生误区,以为返回的是单纯的Dept对象集合

此时deptMapper.selectDept(name, status)返回的对象为page对象,为list接口的一个实现类

page对象中不仅有Dept数据集合,还有着页码等信息

ini 复制代码
List<User> data = page.getResult();
long total = page.getTotal();

实际项目中,更多的是pageInfo来接收数据:

ini 复制代码
List<Dept> list=deptMapper.selectDept(name, status);
//PageInfo的构造器中将page的结果集合分页属性拆分
PageInfo<Dept> pageInfo=new PageInfo<>(list);
pageResult.setRows(pageInfo.getList());
pageResult.setTotal(pageInfo.getTotal());

一是因为Controller层不应该直接依赖MyBatis持久层

二是Page中有很多前端不需要的属性,直接返回会污染接口。

而PageInfo 把 Page 的 20+ 个属性精简整理,只返回前端常用的

相关推荐
用户98883218717419 分钟前
给 .NET 网络调用设定“预算”:用 CancellationTokenSource.CancelAfter 处理超时取消
后端
清风儿32923 分钟前
一块不会说话的电表,把我们折腾了半个月
后端
预知同行35 分钟前
深入解析 MoE 混合专家模型:从 Router 到 All-to-All 的架构全景与生产实践
后端·架构
upala35 分钟前
【仓颉语言入门 · 第二篇 第 8 课】
后端
weiwin1231 小时前
MAF 入门(8):多模态实战——让 Agent 看懂图片、处理混合内容
人工智能·后端
弈栈录1 小时前
流式对话接口设计:SSE、WebSocket 与断线重连
后端
Java内核笔记1 小时前
Spring AI 生产级 Chat 接口:6 个开关、13 个坑,其中 2 个开关根本没生效
java·人工智能·后端
是江迪呀2 小时前
向全世界售卖你的产品:做了一款教程引导插件
前端·javascript·后端
WeiXin_DZbishe2 小时前
基于springboot装修风格选择系统的设计与开发-计算机毕设【课程设计】77964
java·vue.js·spring boot·后端·python·php·课程设计
leikooo2 小时前
ARTS 1018: 字符计数判断异位词、局部做对仍会增加维护负担与用 AI 也要理解自己在做什么
后端