返回顶部
首页 > 资讯 > 精选 >pagehelper分页乱套问题如何解决
  • 749
分享到

pagehelper分页乱套问题如何解决

2023-07-04 16:07:37 749人浏览 独家记忆
摘要

本篇内容介绍了“pagehelper分页乱套问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用pagehelper遇到的坑说明现

本篇内容介绍了“pagehelper分页乱套问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    使用pagehelper遇到的坑说明

    现象是这样的:我们有一个场景是查询数据库表中的全量记录返回给第三方,但是突然某一天发现第三方告警说我们给的数据不对了,比如之前会给到200条记录的,某次只给到了10条记录。

    随后我们推出了几个猜想:

    第三方系统处理数据有bug,漏掉了一些数据;

    数据库被人临时改掉过,然后又被复原了;

    数据库bug,在全量select时可能不返回全部记录;

    其实以上猜想都显得有点无厘头,比如数据库怎么可能有这种低级bug?但是人在没有办法的情况下只能胡猜一通了。最后终于发现是pagehelper的原因,因为分页乱套了,复用了其他场景下的分页设置,丢到数据库查询后返回了10条记录;

    pagehelper的至简使用方式

    本身pagehelper就是一个辅助工具类,所以使用起来一般很简单。尤其在SpringBoot中,只要引用starter类,依赖就可以满足了。(如果是其他版本,则可能需要配置下mybatis的intercepter)

    <!-- https://mvnrepository.com/artifact/com.GitHub.pagehelper/pagehelper-spring-boot-starter -->        <dependency>            <groupId>com.github.pagehelper</groupId>            <artifactId>pagehelper-spring-boot-starter</artifactId>            <version>${pagehelper.version}</version>        </dependency>

    在使用时只需要加上 Page.startPage(pageNum, pageSize) 即可。

    public Object getUsers(int pageNum, int pageSize) {        PageHelper.startPage(pageNum, pageSize);        List<UserEntity> list = userMapper.selectAllWithPage(null);        com.github.pagehelper.Page listWithPage = (com.github.pagehelper.Page) list;        System.out.println("listCnt:" + listWithPage.getTotal());        return list;    }

    而真正的sql里只需按没有分页的样式写一下就可以了。

    <select id="selectAllWithPage" parameterType="java.util.Map"        resultType="com.my.mvc.app.dao.entity.UserEntity">        select * from t_users    </select>

    还是很易用的。少去了一些写死的sql样例。

    pagehelper实现原理简说

    pagehelper不是什么高深的组件,实际上它就是一个mybatis的一个插件或者拦截器。是mybatis在执行调用时,将请求转发给pagehelper处理,然后由pagehelper包装分页逻辑。

    // com.github.pagehelper.PageInterceptor#intercept    @Override    public Object intercept(Invocation invocation) throws Throwable {        try {            Object[] args = invocation.getArgs();            MappedStatement ms = (MappedStatement) args[0];            Object parameter = args[1];            RowBounds rowBounds = (RowBounds) args[2];            ResultHandler resultHandler = (ResultHandler) args[3];            Executor executor = (Executor) invocation.getTarget();            CacheKey cacheKey;            BoundSql boundSql;            //由于逻辑关系,只会进入一次            if (args.length == 4) {                //4 个参数时                boundSql = ms.getBoundSql(parameter);                cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);            } else {                //6 个参数时                cacheKey = (CacheKey) args[4];                boundSql = (BoundSql) args[5];            }            checkDialectExists();            List resultList;            //调用方法判断是否需要进行分页,如果不需要,直接返回结果            if (!dialect.skip(ms, parameter, rowBounds)) {                //判断是否需要进行 count 查询                if (dialect.beforeCount(ms, parameter, rowBounds)) {                    //查询总数                    Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);                    //处理查询总数,返回 true 时继续分页查询,false 时直接返回                    if (!dialect.afterCount(count, parameter, rowBounds)) {                        //当查询总数为 0 时,直接返回空的结果                        return dialect.afterPage(new ArrayList(), parameter, rowBounds);                    }                }                resultList = ExecutorUtil.pageQuery(dialect, executor,                        ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);            } else {                //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页                resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);            }            return dialect.afterPage(resultList, parameter, rowBounds);        } finally {            if(dialect != null){                dialect.afterAll();            }        }    }

    如果没有分页逻辑需要处理,和普通的没什么差别,如果有分页请求,则会在原来的sql之上套上limit.. offset.. 之类的关键词。从而完成分页效果。

    为什么pagehelper的分页会乱套?

    现在我们来说说为什么分页会乱套?原因是 PageHelper.startPage(xx) 的原理是将分页信息设置到线程上下文中,然后在随后的查询中使用该值,使用完成后就将该信息清除。

        public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count) {        return startPage(pageNum, pageSize, count, null, null);    }        public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {        Page<E> page = new Page<E>(pageNum, pageSize, count);        page.setReasonable(reasonable);        page.setPageSizeZero(pageSizeZero);        //当已经执行过orderBy的时候        Page<E> oldPage = getLocalPage();        if (oldPage != null && oldPage.isOrderByOnly()) {            page.setOrderBy(oldPage.getOrderBy());        }        setLocalPage(page);        return page;    }    protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();        protected static void setLocalPage(Page page) {        LOCAL_PAGE.set(page);    }    // com.github.pagehelper.PageHelper#afterAll    @Override    public void afterAll() {        //这个方法即使不分页也会被执行,所以要判断 null        AbstractHelperDialect delegate = autoDialect.getDelegate();        if (delegate != null) {            delegate.afterAll();            autoDialect.clearDelegate();        }        clearPage();    }        public static void clearPage() {        LOCAL_PAGE.remove();    }

    那么什么情况下会导致分页信息乱套呢?实际上就是线程变量什么情况会被乱用呢?

    线程被复用的时候,将可能导致该问题。比如某个请求将某个线程设置了一个线程变量,然后随后另一个请求复用了该线程,那么这个变量就被复用过去了。那么什么情况下线程会被复用呢?

    一般是线程池、连接池等等。是的,大概就是这么原理了。

    分页问题复现

    既然从理论上说明了这个问题,能否稳定复现呢?咱们编写下面的,很快就复现了。

    @RestController@RequestMapping("/hello")@Slf4jpublic class HelloController {    @Resource    private UserService userService;    // 1. 先请求该getUsers接口,将得到异常,pageNum=1, pageSize=1    @GetMapping("getUsers")    @ResponseBody    public Object getUsers(int pageNum, int pageSize) {        return userService.getUsers(pageNum, pageSize);    }    // 2. 多次请求该 getAllActors接口,正常情况下会得到N条全表记录,但将会偶发地得到只有一条记录,现象复现    @GetMapping("getAllActors")    @ResponseBody    public Object getAllActors() {        return userService.getAllActors();    }}@Service@Slf4jpublic class UserService {    @Resource    private UserMapper userMapper;    public Object getUsers(int pageNum, int pageSize) {        PageHelper.startPage(pageNum, pageSize);        // 此处强行抛出异常, 使以上 pagehelper 信息得以保存        throw new RuntimeException("exception ran");    }    public Object getAllActors() {        // 正常的全表查询        List<ActorEntity> list = userMapper.selectAllActors();        return list;    }}

    验证步骤及结果如下:(数据方面,自己随便找一些表就好了)

    // 步骤1: 发送请求: Http://localhost:8081/hello/getUsers?pageNum=1&pageSize=1
    // 步骤2: 发送请求: http://localhost:8081/hello/getAllActors
    // 正常时返回
    [{"actorId":1,"firstName":"PENELOPE","lastName":null,"lastUpdate":null},{"actorId":2,"firstName":"NICK","lastName":null,"lastUpdate":null},{"actorId":3,"firstName":"ED","lastName":null,"lastUpdate":null},{"actorId":4,"firstName":"JENNIFER","lastName":null,"lastUpdate":null},{"actorId":5,"firstName":"JOHNNY","lastName":null,"lastUpdate":null},{"actorId":6,"firstName":"BETTE","lastName":null,"lastUpdate":null},{"actorId":7,"firstName":"GRACE","lastName":null,"lastUpdate":null},{"actorId":8,"firstName":"MATTHEW","lastName":null,"lastUpdate":null},{"actorId":9,"firstName":"JOE","lastName":null,"lastUpdate":null},{"actorId":10,"firstName":"CHRISTIAN","lastName":null,"lastUpdate":null},{"actorId":11,"firstName":"ZERO","lastName":null,"lastUpdate":null},{"actorId":12,"firstName":"KARL","lastName":null,"lastUpdate":null},{"actorId":13,"firstName":"UMA","lastName":null,"lastUpdate":null},{"actorId":14,"firstName":"VIVIEN","lastName":null,"lastUpdate":null},{"actorId":15,"firstName":"CUBA","lastName":null,"lastUpdate":null},{"actorId":16,"firstName":"FRED","lastName":null,"lastUpdate":null},... 
    // 出异常时返回
    [{"actorId":1,"firstName":"PENELOPE","lastName":null,"lastUpdate":null}]

    “pagehelper分页乱套问题如何解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: pagehelper分页乱套问题如何解决

    本文链接: https://lsjlt.com/news/346432.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • pagehelper分页乱套问题如何解决
      本篇内容介绍了“pagehelper分页乱套问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用pagehelper遇到的坑说明现...
      99+
      2023-07-04
    • 解决pageHelper分页失效以及如何配置问题
      目录pageHelper分页失效及配置问题原因解决方案PageHelper分页无效及报错第一种情况SQL报错第二种情况分页无效总结pageHelper分页失效及配置问题 我在使用pa...
      99+
      2023-05-14
      pageHelper分页失效 pageHelper分页配置 pageHelper分页
    • 怎么解决pageHelper分页失效及如何配置问题
      本篇内容主要讲解“怎么解决pageHelper分页失效及如何配置问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么解决pageHelper分页失效及如何配置问题”吧!pageHelper分页...
      99+
      2023-07-05
    • 如何解决html网页乱码问题
      这篇文章主要为大家展示了“如何解决html网页乱码问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决html网页乱码问题”这篇文章吧。组成html网页乱...
      99+
      2024-04-02
    • 如何解决PHP部分乱码问题
      乱码是在Web开发过程中常见的问题之一,特别是在PHP编程中。如果您在PHP页面上看到了乱码,您可以采取一些方法来解决这个问题,这篇文章会详细介绍如何解决PHP部分乱码问题。什么是乱码?乱码是指在HTTP请求和响应中传递的数据中包含了无法被...
      99+
      2023-05-14
      php 乱码
    • 如何解决php翻页出现乱码问题
      本文操作环境:windows7系统、PHP7.1版、Dell G3电脑。如何解决php翻页出现乱码问题?具体问题描述:php分页乱码.php写的分页代码,在网页中显示乱码。分页的代码如下。在网页中显示的是:鏄剧ず绗� 0-0 鏉¤褰曪紝鍏...
      99+
      2015-01-03
      php
    • 解决VuePress页面乱码问题
      目录VuePress页面乱码问题官方步骤VuePress 初探建立文件夹安装 vuepress初始化新建文件夹配置页面启动乱码VuePress页面乱码问题 公司有一个业务场景,需要用...
      99+
      2024-04-02
    • 如何解决mysql深分页问题
      今天小编给大家分享一下如何解决mysql深分页问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一...
      99+
      2024-04-02
    • php页面输出值乱码问题如何解决
      这篇文章主要介绍了php页面输出值乱码问题如何解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇php页面输出值乱码问题如何解决文章都会有所收获,下面我们一起来看看吧。1.设置字符集PHP应用程序输出到页面的字...
      99+
      2023-07-05
    • 解决Mybatis-Plus或PageHelper多表分页查询总条数不对问题
      Mybatis-Plus版本3.4之后,对分页查询进行了优化 对于单表查询是没有问题的。而需要多表关联查询(自写sql)时,就会查询调用Mybatis-Plus的 .page(E page, Wrapper queryWrapper);...
      99+
      2023-08-21
      mybatis java mysql
    • 如何解决phpmyadmin乱码问题
      本篇文章主要探讨如何解决phpmyadmin乱码问题。有一定的参考价值,有需要的朋友可以参考一下,跟随小编一起来看解决方法吧。phpmyadmin数据库乱码?一、在phpMyAdmin中查看服务器编码登陆p...
      99+
      2024-04-02
    • 如何解决em乱码问题
      如何解决em乱码问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 今天登陆em发现出现部分乱码:在网上试好的方...
      99+
      2024-04-02
    • 如何解决mysql乱码问题
      小编给大家分享一下如何解决mysql乱码问题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!  mysql的字符集支持(character set support)有两个方面:字...
      99+
      2024-04-02
    • html如何解决乱码问题
      小编给大家分享一下html如何解决乱码问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!如果想要正确显示 HTML 页面,你要让浏览器知道你使用了哪种字符集。浏览...
      99+
      2023-06-27
    • 如何解决win10乱码问题
      这篇文章主要为大家展示了“如何解决win10乱码问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决win10乱码问题”这篇文章吧。进入控制面板,点击时钟和区域,如下图所示。进入时钟和区域...
      99+
      2023-06-26
    • PHPShellUnrar乱码问题如何解决
      本篇内容主要讲解“PHPShellUnrar乱码问题如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHPShellUnrar乱码问题如何解决”吧!问题描述当使用PHPShellUnrar...
      99+
      2023-07-05
    • php如何解决乱码问题
      这篇文章主要讲解了“php如何解决乱码问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php如何解决乱码问题”吧!什么是乱码在网页开发中,乱码是指在浏览器中显示的字符集和实际编码不一致,导...
      99+
      2023-07-05
    • 如何解决mysql深度分页问题
      目录mysql深度分页问题1.基本分页:耗时0.019秒2.深度分页:耗时10.236秒3.深度ID分页:耗时0.052秒4.两步走深度分页:耗时0.049秒+0.017秒5.一步走深度分页:耗时0.05秒6.集成Bea...
      99+
      2023-01-09
      mysql深度分页 深度分页 mysql分页
    • 如何解决php传递页面参数乱码问题
      本文操作环境:Windows7系统,PHP7.4版,Dell G3电脑。如何解决php传递页面参数乱码问题?php get传值 中文参数 乱码问题的尝试解决:网站的中文参数是直接传的 例如 /index.phpt=你好所有页面均为utf-8...
      99+
      2015-06-19
      php
    • 如何解决php 5.5乱码问题
      本文操作环境:Windows7系统、php5.5版、DELL G3电脑如何解决php 5.5乱码问题?保证各个地方保证同一种编码,假如都是utf-8html5页面:<meta charset='utf-8'>2、...
      99+
      2015-03-24
      php 5.5
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作