Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >深入理解分页及 PageHelper 使用细节与注意事项

深入理解分页及 PageHelper 使用细节与注意事项

作者头像
九转成圣
发布于 2024-11-21 05:49:26
发布于 2024-11-21 05:49:26
1.9K02
代码可运行
举报
文章被收录于专栏:csdncsdn
运行总次数:2
代码可运行

深入理解分页及 PageHelper 使用细节与注意事项

分页是现代应用开发中必不可少的一环,尤其在面对大数据量的场景时,通过分页可以有效减少单次查询的返回数据量,提升性能和用户体验。在 Java 开发中,PageHelper 是一个非常流行的分页插件,简单易用。然而,如果对其原理和使用细节不够了解,在实际使用中容易掉坑。本文将详细介绍 PageHelper 的工作机制、使用方法、常见问题及解决方案,帮助开发者正确使用它,避免踩坑。

一、PageHelper 的基本使用

1. 配置 PageHelper

在使用 PageHelper 之前,需要引入相关依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>

如果使用的是 Spring Boot 项目,只需引入以上依赖即可,无需额外配置。PageHelper 会自动集成 MyBatis。

2. 使用方式

PageHelper 的核心方法是 PageHelper.startPage(),它的作用是为当前线程开启分页上下文,并在接下来的查询中拦截 SQL,添加分页参数。

以下是典型的分页代码示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(inputDto.getPageNum(), inputDto.getPageSize());
List<DevicePushConfig> configList = devicePushConfigMapper.queryDevicePushConfigList(query);
PageInfo<DevicePushConfig> pageInfo = new PageInfo<>(configList);

执行流程

  1. PageHelper.startPage() 开启分页上下文,并设置分页参数。
  2. 查询方法 devicePushConfigMapper.queryDevicePushConfigList(query) 被拦截,PageHelper 在 SQL 后自动添加 LIMIT
  3. 查询返回结果后,使用 PageInfo 封装结果,同时计算总记录数、分页信息等。

二、PageHelper 的工作机制

PageHelper 利用 MyBatis 的插件机制拦截查询语句,在查询 SQL 中自动加入分页语法,如 MySQLLIMIT 或 Oracle 的 ROWNUM,并执行两次 SQL 查询:

  1. 查询总记录数:执行 SELECT COUNT(*) FROM ... 获取满足条件的记录总数。
  2. 查询分页数据:在原始查询 SQL 后追加分页条件。

三、PageHelper 使用中的常见问题及解决方法

1. 分页上下文未清理导致干扰
问题

如果在同一线程中多次调用 PageHelper.startPage(),而未清理上下文,后续查询可能会受到前一次分页的影响。

场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<DataA> listA = mapperA.queryDataA(); // 第一次分页查询

PageHelper.startPage(2, 5);
List<DataB> listB = mapperB.queryDataB(); // 第二次分页查询

PageInfo<DataA> pageInfoA = new PageInfo<>(listA); // 结果可能被第二次分页干扰
解决方法

在每次分页查询后,调用 PageHelper.clearPage() 清理上下文。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<DataA> listA = mapperA.queryDataA();
PageInfo<DataA> pageInfoA = new PageInfo<>(listA);
PageHelper.clearPage(); // 清理上下文

PageHelper.startPage(2, 5);
List<DataB> listB = mapperB.queryDataB();
PageInfo<DataB> pageInfoB = new PageInfo<>(listB);
PageHelper.clearPage();

2. 查询未执行导致上下文污染
问题

如果分页查询代码在条件分支中,而分支未被执行,分页上下文未被清理会干扰后续查询。

场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
if (someCondition) {
    List<Data> list = mapper.queryData(); // 查询未执行
}
// 后续查询会被干扰
解决方法
  • 将分页查询代码移到条件分支内部,确保分页逻辑与查询一一对应。
  • 在条件分支中调用 PageHelper.clearPage() 清理上下文。

3. 数据转换后分页信息丢失
问题

如果分页查询返回的结果被转换为另一种类型(例如 DTO),再使用 PageInfo 封装,可能会导致分页总数信息丢失。

场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<DevicePushConfig> configList = mapper.queryDevicePushConfigList(query);

// 数据转换
List<DevicePushConfigOutputDto> result = new ArrayList<>();
for (DevicePushConfig config : configList) {
    DevicePushConfigOutputDto dto = new DevicePushConfigOutputDto();
    BeanUtils.copyProperties(config, dto);
    result.add(dto);
}

// 使用 PageInfo 封装
PageInfo<DevicePushConfigOutputDto> pageInfo = new PageInfo<>(result); // 总数信息丢失
解决方法

分页封装应基于原始查询结果,然后再进行数据转换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<DevicePushConfig> configList = mapper.queryDevicePushConfigList(query);
PageInfo<DevicePushConfig> pageInfo = new PageInfo<>(configList);

// 数据转换
List<DevicePushConfigOutputDto> result = pageInfo.getList().stream()
    .map(config -> {
        DevicePushConfigOutputDto dto = new DevicePushConfigOutputDto();
        BeanUtils.copyProperties(config, dto);
        return dto;
    })
    .collect(Collectors.toList());
pageInfo.setList(result);

4. 分页与排序冲突
问题

如果分页查询包含排序逻辑,而排序字段未建立索引,可能导致性能问题。

场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * FROM table_a
ORDER BY create_time
LIMIT 0, 10;
解决方法
  • 确保排序字段上建立索引。
  • 对于大表分页,可以使用基于主键的范围查询优化:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * FROM table_a
WHERE id > #{lastId}
ORDER BY id ASC
LIMIT 10;

5. 重复分页
问题

分页逻辑已经通过数据库完成,如果开发者额外对结果进行代码级分页,可能导致结果不完整。

场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<Data> dataList = mapper.queryData();

// 再次手动分页
List<Data> pagedResult = dataList.subList(0, Math.min(dataList.size(), 5));
解决方法

避免重复分页,直接使用 PageInfo 提供的分页信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PageHelper.startPage(1, 10);
List<Data> dataList = mapper.queryData();
PageInfo<Data> pageInfo = new PageInfo<>(dataList);

四、总结

PageHelper 是一个非常强大的分页工具,但其使用过程中需要注意以下细节:

  1. 分页上下文管理:分页查询后必须清理上下文,防止干扰后续查询。
  2. 查询逻辑顺序:确保 PageHelper.startPage() 在查询前调用。
  3. 数据转换问题:封装分页对象时,注意保持分页信息的一致性。
  4. 性能优化:复杂 SQL 或排序字段需优化索引,避免全表扫描。
  5. 避免重复分页:不要对已分页的数据再进行代码级分页。

通过正确理解和使用 PageHelper,开发者可以高效完成分页需求,同时规避潜在问题,提升系统性能与稳定性。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
用了这么多年分页PageHelper,才发现自己一直用错了!
在实际项目运用中,PageHelper的使用非常便利快捷,仅通过PageInfo + PageHelper两个类,就足以完成分页功能,然而往往这种最简单的集成使用方式,却在很多实际应用场景中,没有得到充分的开发利用.
业余草
2020/10/29
10.1K0
一次因PageHelper引起的多线程复用问题的排查和解决
导读 本文不仅对遇到类似问题的开发者提供了实际的解决思路,也为希望深入理解PageHelper工作机制和多线程编程的读者提供了丰富的技术细节。无论是对于中级开发者还是有经验的架构师,本文的内容都具有一定的参考价值。
京东技术
2024/03/18
4430
一次因PageHelper引起的多线程复用问题的排查和解决
PageHelper 真的会用么?
PageHelper 用法,在serviceimpl 执行mapper前 加入 PageHelper.startPage(page, pageSize),在new PageInfo<>(T) 即可
收心
2022/01/19
3130
MyBatis分页插件PageHelper的使用
从图中可以看出,mybatis中首先要在配置文件中配置一些东西,然后根据这些配置去创建一个会话工厂,再根据会话工厂创建会话,会话发出操作数据库的sql语句,然后通过执行器操作数据,再使用mappedStatement对数据进行封装,这就是整个mybatis框架的执行情况。那么mybatis的插件作用在哪一环节呢?它主要作用在Executor执行器与mappedeStatement之间,也就是说mybatis可以在插件中获得要执行的sql语句,在sql语句中添加limit语句,然后再去对sql进行封装,从
似水的流年
2018/06/13
1.8K0
MyBatis分页组件--PageHelper
PageHelper是国内非常优秀的一款开源的 mybatis 分页插件,它支持基本主流与常用的数据库,例如 Oracle、Mysql、MariaDB、SQLite、Hsqldb 等。
宋先生
2019/07/18
1.2K0
Mybatisplus的查询
首先要引入mabtisplus的分页拦截器,官方已经提供MybatisPlusConfig
名字是乱打的
2021/12/24
1K0
Mybatisplus的查询
Pagehelper超级好用的分页插件
ma布
2024/10/21
2700
记一次PageHelper分页未生效问题排查
最近在项目中使用PageHelper分页工具+Mybatis实现分页查询逻辑,但是发现分页逻辑并没有生效,代码片段如下:
眯眯眼的猫头鹰
2022/03/23
1.7K0
Mybatis分页插件PageHelper的配置和使用方法
前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页。 前端分页 一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作。 特点是:简单,很适合小规模的web平台;当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长。 后端分页 在ajax请求中指定页码(pageNum)和每页的大小(pageSize),后端查询出当页的数据返回,前端只负责
用户1225216
2018/03/05
5.1K0
SpringBoot整合分页插件PageHelper
在springboot中使用PageHelper插件有两种较为相似的方式,接下来我就将这两种方式进行总结。官方使用说明
zpzp6
2023/03/23
1.4K0
PageHelper 插件,无故给 SQL 增加 Limit 问题
在项目中,使用了 MyBatis 的 PageHelper 插件,发现了一个奇怪的问题,经常会给SQL无缘无故的增加Limit语句,经过调查,发现原因是没有安全的使用PageHelper插件,先来看一个例子:
BUG弄潮儿
2021/12/08
2.2K0
PageHelper分页插件
PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。
2020/10/23
1.1K0
PageHelper分页插件
springboot集成mybatisplus分页_mybatis分页查询原理
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/194202.html原文链接:https://javaforall.cn
全栈程序员站长
2022/10/02
8220
java 的 pagehelper.PageHelper实现分页的逻辑
目录 1 需求 2 实现 3 原理 1 需求 我们想要在Java代码里面实现分页,那么可以使用第三方的插件 2 实现 1 倒入依赖 <!-- PageHelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1
一写代码就开心
2023/02/02
5520
【MyBatis】MyBatis分页插件PageHelper的使用
转载自 https://www.cnblogs.com/shanheyongmu/p/5864047.html   
allsmallpig
2021/02/25
8560
springboot整合mybatis分页插件PageHelper实战
https://www.cnblogs.com/xifengxiaoma/p/11027551.html
全栈程序员站长
2022/11/03
1.5K0
MyBatis 的分页方式,你都会吗
分页是我们在开发中绕不过去的一个坎!当你的数据量大了的时候,一次性将所有数据查出来不现实,所以我们一般都是分页查询的,减轻服务端的压力,提升了速度和效率!也减轻了前端渲染的压力!
Java技术精选
2021/09/15
1.5K0
Springboot引入pageHelper流程以及小坑
mybatisplus自带的插件一般用于我们使用其自带的sql操作api,比如查询的时候加一个ipage,这一般不适用于我们自己写的sql操作,想应用于自定义sql比较麻烦,这里介绍一款我们mybatis和mybatisplus都可以使用的分页插件pagehelper mybatis引用
名字是乱打的
2021/12/24
1.8K0
sql2java-pagehelper:参照Mybatis-PageHelper实现分页查询
sql2java是我几年年开始写的一个sql2java是一个轻量级数据库(SQL)访问代码(java)生成器。这几年一直在根据工作需要维护升级,最近的项目中需要对数据库的记录提供分页查询功能,于是我参照Mybatis-PageHelper并借用其外部数据格式为sql2java实现的分页功能,将其封装为一个sql2java子项目sqlj2ava-pagehelper。使用方式与Mybatis-Pagehelper基本一致。
10km
2022/09/27
3600
Mybatis分页插件-PageHepler的使用
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pyycsd/article/details/80969700
用户1212940
2019/06/20
1.1K0
推荐阅读
相关推荐
用了这么多年分页PageHelper,才发现自己一直用错了!
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验