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 的提供的分页方法方法时,分页插件才会生效,自动拦截和处理分页逻辑。

相关推荐
昵称为空C几秒前
在复杂SpringBoot项目中基于hutool实现临时添加多数据源案例
spring boot·后端
金融数据出海35 分钟前
韩国股票 API 对接指南 Seoul&KOSDAQ
后端
geovindu36 分钟前
go: Simple Factory Pattern
开发语言·后端·设计模式·golang·简单工厂模式
咕白m62536 分钟前
Python 高效添加与管理 Excel 工作表
后端·python
计算机学姐43 分钟前
基于SpringBoot的房屋交易系统
java·vue.js·spring boot·后端·spring·intellij-idea·mybatis
java1234_小锋1 小时前
SpringBoot 4 + Spring Security 7 + Vue3 前后端分离项目设计最佳实践
spring boot·后端·spring
今夕资源网1 小时前
indextts API 阅读 API 重磅升级!低延迟 + 音色管理 + 缓存全拉满 支持开源阅读小说软件,其他软件应该也通用
java·后端·spring
Rick19931 小时前
Spring Cloud 原理是什么?
后端·spring·spring cloud
掘金者阿豪2 小时前
从死守 Windows 到彻底 Mac 化:程序员一旦用了 Mac,真的很难再回去
后端
阿里加多2 小时前
第 5 章:Go 内存模型与 Happens-Before 原则
开发语言·后端·golang