前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java|PageHelper 怎么自作主张帮我分页?

Java|PageHelper 怎么自作主张帮我分页?

作者头像
mzlogin
发布于 2024-05-21 12:40:33
发布于 2024-05-21 12:40:33
13500
代码可运行
举报
文章被收录于专栏:闷骚的程序员闷骚的程序员
运行总次数:0
代码可运行

开局上来,我们先看看问题场景的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Page<Xxx> queryXxxList(XxxPageReq req) {

    // some code here

    // 查询一,得到一个结果集,作为查询二的条件
    List<Long> fkIdList = xxxMapper.queryFkIdList(req);
    req.setFkIdList(idList);

    PageHelper.startPage(req.getPageNum(), req.getPageSize());

    // 查询二
    List<Xxx> data = xxxMapper.queryXxxList(req);

    // some code here

}

预期 的逻辑是:查询一不分页,得到一个结果集,作为查询二的条件,查询二分页。

实际 的现象是:查询一被自动添加了 limit,最多只能查询到 10 条数据(示例 req 里的 pageSize 传的 10),导致查询二的查询条件不正确。

分析

初遇到这个问题时,一脸黑人问号,冷静下来后,分析了以下几种可能性,但都一一排除了。

  • 调用当前方法的线程里,已经有其它地方先调用了 PageHelper.startPage(),导致当前方法里的查询一也被分页了;
  • 调用当前方法的线程,上一次调度时设置的分页参数没有被清理;
  • 无厘头的猜想:当前方法是不是在一个大的事务里,而 PageHelper 有什么特殊处理,导致一个事务里的查询都会被分页?

最后通过在 PageInterceptor 里下断点发现了问题所在:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public Object intercept(Invocation invocation) throws Throwable {
    // some code here 

    //调用方法判断是否需要进行分页,如果不需要,直接返回结果
    if (!dialect.skip(ms, parameter, rowBounds)) {
        // 自动 count 和 分页查询处理
    } else {
        // 跳过 count 和 分页查询处理
    }
    // some code here
}

单步跟进 dialect.skip 方法,关键逻辑在 PageParams.getPage 方法里面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Page getPage(Object parameterObject, RowBounds rowBounds) {
    Page page = PageHelper.getLocalPage();
    if (page == null) {
        if (rowBounds != RowBounds.DEFAULT) {
            if (offsetAsPageNum) {
                page = new Page(rowBounds.getOffset(), rowBounds.getLimit(), rowBoundsWithCount);
            } else {
                page = new Page(new int[]{rowBounds.getOffset(), rowBounds.getLimit()}, rowBoundsWithCount);
                //offsetAsPageNum=false的时候,由于PageNum问题,不能使用reasonable,这里会强制为false
                page.setReasonable(false);
            }
        } else if(supportMethodsArguments){
            // 注意这里,我们的查询一进了这个分支
            try {
                page = PageObjectUtil.getPageFromObject(parameterObject, false);
            } catch (Exception e) {
                return null;
            }
        }
        if(page == null){
            return null;
        }
        PageHelper.setLocalPage(page);
    }
    // some code here
}

可以看到,除了显式地提前调用 PageHelper.startPage、传递 rowBounds 参数进行分页外,还有一个 else if(supportMethodsArguments) 的分支,会从传递给查询的参数里尝试读取 pageNumpageSize 字段的值作为分页参数。

随后我查阅了 PageHelper 的官方文档,果然找到了相关的说明:

supportMethodsArguments:支持通过 Mapper 接口参数来传递分页参数,默认值 false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和 ArgumentsObjTest。

https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

那么,为什么我们项目里的 supportMethodsArguments 会为 true 呢?在代码里没有搜索到,最终在 Apollo 配置中心找到了 pagehelper.supportMethodsArguments = true

破案了。

解决

找到问题就好解决了。因为将 pagehelper.supportMethodsArguments = true 这个配置去掉影响太大不可控,所以此处只是将查询一的参数去掉分页字段即可。

修改后:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Page<Xxx> queryXxxList(XxxPageReq req) {

    // some code here

    // 查询一,得到一个结果集,作为查询二的条件
    // XxxNoPageReq 与 XxxPageReq 里的字段一样,除了没有 pageSize 和 pageNum
    XxxNoPageReq noPageReq = new XxxNoPageReq();
    BeanUtils.copyProperties(req, noPageReq);
    List<Long> fkIdList = xxxMapper.queryFkIdList(noPageReq);

    // some code here

}

小结

修完老代码里的这个问题,我无奈地笑了。真是前人挖坑,后人被坑啊……

开个玩笑。

这严格来说,其实并不能算一个问题,包括解决它需要走的那些弯路,都只能归咎于对 PageHelper 的用法,以及项目的配置,了解不完全。

码途漫漫,上下求索。

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Mybatis分页插件: pageHelper的使用及其原理解析
在实际工作中,很进行列表查询的场景,我们往往都需要做两个步骤:1. 查询所需页数对应数据;2. 统计符合条件的数据总数;而这,又会导致我们必然至少要写2个sql进行操作。这无形中增加了我们的工作量,另外,当发生需要变动时,我们又需要同时改动这两个sql,否则必然导致结果的不一致。
烂猪皮
2021/01/28
29.6K0
Mybatis分页插件: pageHelper的使用及其原理解析
Mybatis分页插件PageHelper详解
作者:一杯甜酒原文:https://blog.csdn.net/u012562943/article/details/51838759https://www.jianshu.com/p/1becdc376f5d
用户5224393
2019/08/13
1.7K0
MyBatis之分页插件(PageHelper)工作原理
  数据分页功能是我们软件系统中必备的功能,在持久层使用mybatis的情况下,pageHelper来实现后台分页则是我们常用的一个选择,所以本文专门类介绍下。
用户4919348
2019/04/02
2K0
MyBatis之分页插件(PageHelper)工作原理
PageHelper分页插件的原理是什么
原文:https://my.oschina.net/zudajun/blog/745232
Bug开发工程师
2019/05/16
5.1K0
PageHelper分页插件的原理是什么
SpringBoot整合分页插件PageHelper
在springboot中使用PageHelper插件有两种较为相似的方式,接下来我就将这两种方式进行总结。官方使用说明
zpzp6
2023/03/23
1.4K0
Mybatis分页插件PageHelper的配置和使用方法
前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页。 前端分页 一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作。 特点是:简单,很适合小规模的web平台;当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长。 后端分页 在ajax请求中指定页码(pageNum)和每页的大小(pageSize),后端查询出当页的数据返回,前端只负责
用户1225216
2018/03/05
5.1K0
Mybatis分页插件 - PageHelper
该插件目前支持Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库分页。
软件小生活
2021/10/20
1.5K0
MyBatis分页插件PageHelper的使用
从图中可以看出,mybatis中首先要在配置文件中配置一些东西,然后根据这些配置去创建一个会话工厂,再根据会话工厂创建会话,会话发出操作数据库的sql语句,然后通过执行器操作数据,再使用mappedStatement对数据进行封装,这就是整个mybatis框架的执行情况。那么mybatis的插件作用在哪一环节呢?它主要作用在Executor执行器与mappedeStatement之间,也就是说mybatis可以在插件中获得要执行的sql语句,在sql语句中添加limit语句,然后再去对sql进行封装,从
似水的流年
2018/06/13
1.8K0
Mybatis分页插件-PageHepler的使用
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pyycsd/article/details/80969700
用户1212940
2019/06/20
1.1K0
Spring boot Mybatis-XML方式分页查询PageHelper(五)
PageHelper介绍 PageHelper是Github上有位开发者写了一个分页插件,可以很方便的添加到MyBatis的拦截器接口中。 Github项目地址 pom.xml添加依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.1.0</version> </dependency> 配置文件编写 @Configur
楠楠
2018/09/11
3.3K0
Spring boot Mybatis-XML方式分页查询PageHelper(五)
Spring Boot 2.x(十三):你不知道的PageHelper
说起PageHelper,使用过Mybatis的朋友可能不是很陌生,作为一款国人开发的分页插件,它基本上满足了我们的日常需求。但是,我想去官方文档看看这个东西配合Spring Boot进行使用的时候,发现了这个:
山禾说
2019/03/19
1.2K0
Spring Boot 2.x(十三):你不知道的PageHelper
开源MyBatis分页插件,省时省力
如何能让自己在使用Mybatis时事半功倍?让自己效率提升释放时间?那么就一定要看看今天TJ君给你介绍的这款Mybatis通用分页开源插件:
程序猿DD
2021/12/01
6840
SpringBoot + mybatis 分页查询
com.github.pagehelper.PageHelper是一款好用的开源免费的Mybatis第三方分页插件。使用的时候,只要简单配置,就可以在查询语句之后得到所需的分页信息。
全栈程序员站长
2022/08/22
1.4K0
SpringBoot + mybatis 分页查询
浅谈使用PageHelper-Mybatis通用分页插件
https://github.com/pagehelper/Mybatis-PageHelperMybatis 框架的分页插件 PageHelper,目前支持 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 等多种数据库分页。插件目前支持以下数据库的物理分页 PageAutoDialect:static { //注册别名 registerDialectAlias("hsqldb",HsqldbDialect.class);
QGS
2023/03/03
1.5K0
分页插件pageHelpler的使用(ssm框架中)服务器端分页
4. serviceImpl 中接收从mapper.xml中查到的结果,运用pagehelper分页 。
微风-- 轻许--
2022/04/13
1K0
只知道用是不行的!浅析pagehelper分页原理
之前项目一直使用的是普元框架,最近公司项目搭建了新框架,主要是由公司的大佬搭建的,以springboot为基础。为了多学习点东西,我也模仿他搭了一套自己的框架,但是在完成分页功能的时候,确遇到了问题。
Java编程指南
2020/06/24
1.4K0
记一次PageHelper分页未生效问题排查
最近在项目中使用PageHelper分页工具+Mybatis实现分页查询逻辑,但是发现分页逻辑并没有生效,代码片段如下:
眯眯眼的猫头鹰
2022/03/23
1.7K0
PageHelper 使用中的一些坑
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/08/29
1K0
PageHelper 使用中的一些坑
一次因PageHelper引起的多线程复用问题的排查和解决
导读 本文不仅对遇到类似问题的开发者提供了实际的解决思路,也为希望深入理解PageHelper工作机制和多线程编程的读者提供了丰富的技术细节。无论是对于中级开发者还是有经验的架构师,本文的内容都具有一定的参考价值。
京东技术
2024/03/18
4390
一次因PageHelper引起的多线程复用问题的排查和解决
其实MyBatis的插件机制可以帮我们解决工作的很多问题,建议收藏!
  在实际的工作对于MyBatis的使用我们更多的还是停留在应用层,如果你对于MyBatis的底层,尤其是插件这块掌握的比较好的,可以帮助我们解决很多工作中比较棘手的问题,本篇文章就给大伙详细的来介绍下MyBatis的插件机制。对于MyBatis的底层原理还有不清楚的可以看看我的MyBatis底层专题哦。
用户4919348
2021/06/01
1.3K0
其实MyBatis的插件机制可以帮我们解决工作的很多问题,建议收藏!
相关推荐
Mybatis分页插件: pageHelper的使用及其原理解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验