PageHelper 的用法比手写 LIMIT 简单得多。它的核心思想是"只改一行代码,不碰 SQL":在要分页的查询之前 ,调用 PageHelper.startPage(pageNum, pageSize) 开启分页功能。
下面以最常用的 Spring Boot 项目为例,介绍完整的操作流程。
1. 引入依赖
在你的 pom.xml 文件中,添加 pagehelper-spring-boot-starter 依赖。
xml
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version> <!-- 建议使用最新稳定版本 -->
</dependency>
这个 Starter 会自动完成配置,无需额外配置拦截器。
2. 可选配置
在 application.yml 或 application.properties 中,可以做一些个性化配置:
yaml
pagehelper:
helper-dialect: mysql # 指定数据库类型,Starter会自动识别,但建议明确指定
reasonable: true # 分页合理化:pageNum<1查第一页,>总页数查最后一页
support-methods-arguments: true # 支持通过 Mapper 接口参数传递分页参数
3. 核心用法
这是PageHelper最标准的用法,三步即可:
第一步:在查询前调用 PageHelper.startPage ,设置页码和每页大小。 第二步:执行一个普通的 Mapper 查询 ,不包含任何分页代码。 第三步:用 PageInfo 封装查询结果,获得完整的分页信息。
完整代码示例:
java
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageInfo<User> findUsersByPage(int pageNum, int pageSize) {
// 1. 开启分页,只对紧随其后的第一个查询生效
PageHelper.startPage(pageNum, pageSize);
// 2. 执行普通查询,PageHelper 会自动拦截并追加 LIMIT
List<User> userList = userMapper.selectAllUsers();
// 3. 用 PageInfo 封装结果,它包含了所有分页信息
PageInfo<User> pageInfo = new PageInfo<>(userList);
return pageInfo;
}
}
4. 返回的 PageInfo 对象里有什么?
PageInfo 对象可以直接返回给前端,它包含了前端分页组件需要的所有信息:
| 属性 | 说明 |
|---|---|
total |
总记录数 |
pages |
总页数 |
pageNum |
当前页码 |
pageSize |
每页数量 |
list |
当前页的数据列表 |
hasPreviousPage |
是否有上一页 |
hasNextPage |
是否有下一页 |
isFirstPage / isLastPage |
是否为第一/最后一页 |
5. ⚠️ 重要注意事项
原理说明
PageHelper 本质上是利用 MyBatis 的拦截器机制,在执行查询前,额外执行一次 SELECT COUNT(*) 来获取总记录数,并在原 SQL 后追加 LIMIT 子句。
核心原则
- 紧挨查询 :
PageHelper.startPage()必须紧挨着它要分页的那个 Mapper 查询方法,中间不能有其他数据库查询操作。 - 只对第一个查询生效 :它只会影响紧随其后的第一个
SELECT查询。 - 不支持
for update:分页插件不支持带有for update的 SQL。
使用陷阱
ThreadLocal污染 :如果在一个线程中调用了PageHelper.startPage(),但后续没有执行查询,分页参数会一直残留,可能意外影响其他查询。解决方法 :可以在每次分页后调用PageHelper.clearPage()手动清理上下文。- 勿重复分页 :如果 Mapper 的 SQL 里已经写了
LIMIT,PageHelper 会再次添加,导致 SQL 语法错误或结果异常。 - 复杂关联查询 :在复杂的多表关联查询中,如果存在
1:N关系,PageHelper 自动生成的COUNT语句可能不准确。
6. 进阶用法
分页的同时进行排序
java
PageHelper.startPage(1, 10).orderBy("id desc");
// 或
PageHelper.startPage(1, 10, "id desc");
手动控制 COUNT 查询
java
// 禁用总记录数查询,用于不需要 total 的场景,可提升性能
PageHelper.startPage(1, 10, false);
// 使用 Lambda 表达式进行分页,可自定义 COUNT 逻辑
PageInfo<User> pageInfo = PageHelper.startPage(1, 10)
.doSelectPageInfo(() -> userMapper.selectUsersWithComplexJoin());
总结
总的来说,引入依赖 → 调用 startPage → 执行查询 → 封装 PageInfo 这四步就是 PageHelper 最核心的使用流程。它把分页逻辑从 SQL 中抽离出来,让代码更干净,也更容易维护。