PageHelper和Mybatis-Plus分页

PageHelperMybatis-Plus 分页,两者都是基于 MyBatis 的拦截器机制来实现分页功能,通过拦截SQL语句并对其进行修改以实现分页。

PageHelper分页插件

在 MyBatis 中,当使用 PageHelper.startPage() 启动分页后,紧跟着的查询方法返回的 List 会被自动封装成一个 Page 对象。

使用

业务层直接调用 PageHelper.startPage(int pageNum, int pageSize) 传入分页参数(当前页码, 分页大小),PageHelper.startPage()之后紧跟查询方法即可。

PageHelper 的底层机制

基于 ThreadLocal 的分页参数传递

  • 调用 startPage() 时,分页参数(页码、每页条数等)会被存入当前线程的 ThreadLocal 变量中。
  • 后续的 MyBatis 查询方法会被 PageInterceptor(分页拦截器)拦截,从 ThreadLocal 中读取分页参数。

拦截器修改 SQL 并封装结果

  • 修改 SQL :拦截器根据分页参数,动态修改原始 SQL,添加数据库方言对应的分页语句(如 MySQL 的 LIMIT)。
  • 执行 COUNT 查询 :自动生成并执行 SELECT COUNT(*) 语句,获取总记录数。
  • 执行当前页查询:执行修改后的 SQL,获取当前页的数据。
  • 封装 Page 对象 :将分页数据和总记录数封装到 Page 对象中,最终返回给调用方。
  • 清理ThreadLocal :分页完成后,PageHelper会自动清除ThreadLocal中的分页参数,避免影响后续无关的查询。

Tips:

拦截器会将分页查询写回 startPage() 返回的 Page 对象中,即就是 PageHelper.startPage() 启动分页后,紧跟着的查询方法返回的 List 对象和 startPage() 返回的 Page 对象是同一个对象。见下图验证。

PagePageInfo对象

Page 对象

  • 本质PageArrayList 的子类,直接承载当前分页的数据集合(如当前页的查询结果列表)。

  • 功能

    • 存储当前页的数据(继承自 List)。
    • 包含基本的分页元数据,如:
      • pageNum:当前页码(从1开始)。
      • pageSize:每页显示条数。
      • total:总记录数(自动通过 COUNT 查询获取)。
      • pages:总页数(由 totalpageSize 计算得出)。
  • 特点

    • 直接关联查询结果 :分页查询后的 List 实际上是 Page 对象,可以直接强制转换获取分页元数据。
    • 轻量级:仅包含当前页数据和基础分页信息。

PageInfo 对象

  • 本质PageInfo 是对 Page增强封装,提供更丰富的分页元数据和工具方法。

  • 功能

    • 包含 Page 的所有分页元数据(如 pageNumpageSizetotal 等)。
    • 扩展了更多分页导航相关的属性,如:
      • isFirstPage/isLastPage:是否第一页/最后一页。
      • hasPreviousPage/hasNextPage:是否有上一页/下一页。
      • navigatePages:导航页码数量(如显示前5页、后5页)。
      • navigatepageNums:导航页码数组(用于生成页码按钮)。
      • prePage/nextPage:上一页/下一页的页码。
  • 特点

    • 脱离数据集合PageInfo 本身不直接存储数据集合,而是通过构造函数接收 List(通常是 Page 对象)来解析元数据。
    • 面向展示层 :更适合前端分页展示,直接提供导航所需的全部信息。

PageInfo 可以通过任何 List 构造,是因为Page对象继承自ArrayList,但实际只有分页后的 List(实际是 Page对象)才能正确解析分页元数据。

Mybatis-Plus分页

MyBatis-Plus 的分页功能基于拦截器实现,需手动配置分页插件。

使用

  • 创建 Page 对象:封装分页参数(当前页、每页条数)。
  • 执行分页查询 :调用MP提供的分页查询方法,传入 Page 和查询条件。
  • 获取分页结果 :返回的 Page 对象包含数据和分页信息。
Java 复制代码
public List<DeviceData> selectDeviceDataList(DeviceDataPageReqDto deviceData){
    Page<DeviceData> deviceDataPage = new Page<>(deviceData.getPageNum(), deviceData.getPageSize());
    this.lambdaQuery()
            .eq(ObjUtil.isNotNull(deviceData.getDeviceId()), DeviceData::getIotId, deviceData.getDeviceId())
            .eq(ObjUtil.isNotNull(deviceData.getFunctionId()), DeviceData::getFunctionId, deviceData.getFunctionId())
            .between(ObjUtil.isNotNull(deviceData.getStartTime()) && ObjUtil.isNotNull(deviceData.getEndTime()),
                    DeviceData::getAlarmTime, deviceData.getStartTime(), deviceData.getEndTime())
            // 执行分页查询
            .page(deviceDataPage);
    List<DeviceData> records = deviceDataPage.getRecords();
    long total = deviceDataPage.getTotal();
    // mapper层提供的分页查询方法示例
    // Page<DeviceData> deviceDataPage1 = deviceDataMapper.selectPage(deviceDataPage, new LambdaQueryWrapper<>());
    return records;
}

Tips:

只有在调用 MyBatis-Plus 的提供的分页方法方法时,分页插件才会生效,自动拦截和处理分页逻辑。

相关推荐
SamDeepThinking1 分钟前
基于CompletableFuture的主子任务并行处理架构实战:多渠道账单并发导入性能提升5倍的技术方案
java·后端·excel
期待のcode2 分钟前
Springboot整合springmvc的自动装配
java·spring boot·后端
古城小栈4 分钟前
SpringBoot Web容器选型指南:Tomcat与Undertow技术对比及迁移实践
spring boot·后端·tomcat
悟能不能悟4 分钟前
springboot的controller中如何拿到applicatim.yml的配置值
java·spring boot·后端
0和1的舞者5 分钟前
《SpringBoot 入门通关指南:从 HelloWorld 到问题排查全掌握》
java·spring boot·后端·网络编程·springboot·开发·网站
考虑考虑7 分钟前
SpringBoot4中api版本控制
spring boot·后端·spring
Jul1en_11 分钟前
【Spring DI】Spring依赖注入详解
java·spring boot·后端·spring
Lisonseekpan16 分钟前
HTTP请求方法全面解析:从基础到面试实战
java·后端·网络协议·http·面试
N***p36519 分钟前
IDEA搭建SpringBoot,MyBatis,Mysql工程项目
spring boot·intellij-idea·mybatis
无奈何杨26 分钟前
业务接入风控决策,挑战验证与结果同步
后端