PageHelper 实现物理分页的核心是在 SQL 执行前动态重写原 SQL 并添加数据库特化分页语句(如 MySQL 的 LIMIT),由数据库直接返回目标页数据。需正确配置 dialect、调用 PageHelper.startPage() 触发拦截,配合 PageInfo 获取总页数等元信息。

PageHelper 实现物理分页,核心在于**在 SQL 执行前动态重写原 SQL,添加数据库特化的分页语句(如 MySQL 的 LIMIT)**,让数据库直接返回目标页的数据,而非查出全部再内存截取。
一、依赖与配置(确保启用物理分页)
PageHelper 默认开启物理分页,但需确认使用的是支持的数据库方言(如 mysql、oracle、postgresql 等)。Maven 引入后,在 MyBatis 配置中注册插件:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>注意:dialect 必须与实际数据库匹配,否则可能退化为内存分页或报错。
二、代码中触发物理分页(关键调用)
在执行查询前,调用 PageHelper.startPage(),传入页码(从 1 开始)和每页条数。之后紧跟着的 Mapper 查询方法即被拦截并改写 SQL:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 正确写法(单次查询生效):
PageHelper.startPage(2, 10); // 第2页,每页10条 List<User> users = userMapper.selectAll(); // 此时发出的 SQL 已含 LIMIT 10,10
-
不推荐写法(易失效):在
startPage()后又执行了其他查询(如另一个select),会导致分页参数被覆盖或清空。 -
注意线程安全:
startPage()基于ThreadLocal,只对当前线程下一次查询有效;Web 场景中建议配合@ControllerAdvice或拦截器统一处理分页参数。
三、SQL 重写原理(以 MySQL 为例)
假设原始 Mapper SQL 是:
SELECT * FROM user WHERE status = 1
PageHelper 拦截后,生成的实际执行 SQL 为:
SELECT * FROM user WHERE status = 1 LIMIT 10, 10
其中 LIMIT 10,10 表示跳过前 10 条,取接下来的 10 条(对应第 2 页)。该过程由 PageInterceptor 在 Executor.query() 前完成,完全交由数据库执行,不加载无关数据到 JVM。
四、获取分页结果(封装 PageInfo)
直接使用 PageHelper.startPage() 返回的是 List,若需总记录数、总页数等元信息,推荐用 PageInfo 包装:
PageHelper.startPage(2, 10); List<User> users = userMapper.selectAll(); PageInfo<User> pageInfo = new PageInfo<>(users); // 自动查询总条数(执行 COUNT(*))
注意:COUNT 查询也受相同方言控制,会生成类似 SELECT COUNT(*) FROM user WHERE status = 1 的语句——这是物理分页配套的“总数量统计”,同样由数据库完成。

















