PageHelper 的用法

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.ymlapplication.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 子句。

核心原则

  1. 紧挨查询PageHelper.startPage() 必须紧挨着它要分页的那个 Mapper 查询方法,中间不能有其他数据库查询操作。
  2. 只对第一个查询生效 :它只会影响紧随其后的第一个 SELECT 查询。
  3. 不支持 for update :分页插件不支持带有 for update 的 SQL。

使用陷阱

  1. ThreadLocal 污染 :如果在一个线程中调用了 PageHelper.startPage(),但后续没有执行查询,分页参数会一直残留,可能意外影响其他查询。解决方法 :可以在每次分页后调用 PageHelper.clearPage() 手动清理上下文。
  2. 勿重复分页 :如果 Mapper 的 SQL 里已经写了 LIMIT,PageHelper 会再次添加,导致 SQL 语法错误或结果异常。
  3. 复杂关联查询 :在复杂的多表关联查询中,如果存在 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 中抽离出来,让代码更干净,也更容易维护。

相关推荐
foggyprojects1 小时前
业务系统有表格,BI 有看板,AI 问数还需要做什么?
后端
生锈的键盘1 小时前
深入理解 Socket 与 epoll:从内核数据结构到用户态回调的全链路解析
后端
Sam_Deep_Thinking1 小时前
从REST到gRPC,一个API选型的思考框架
java·后端·程序员
无毁的湖光-Al2 小时前
解Bug之路-with AI-应用被限流?
java·linux
程序员贺加贝2 小时前
别把 ThreadLocal 写进 Serializer:一次 SaaS 多租户 Jackson 上下文污染排查
java·spring boot
程序员爱钓鱼2 小时前
Rust const泛型详解:让常量也成为泛型参数
后端·面试·rust
许彰午2 小时前
06-EaEngine调度器
java·低代码·架构
evans在进步2 小时前
Spring Boot 工程化核心详解:Parent、Starter、热部署、事务与多数据源
spring boot·后端·python
卓怡学长2 小时前
w181springboot机场乘客服务系统
java·数据库·spring boot·spring·intellij-idea