• PageHelper插件原理


    介绍

    PageHelper是一个很好的mybatis分页插件。经过简单的配置,只需要几行代码就可以实现分页查询。

    数据库数据如下:

     @RequestMapping("/findAllUser")

    public ResponseResult<PageBean> findAllUser2(PageModel pageModel) {
      PageHelper.startPage(pageModel.getPageNum(), pageModel.getPageSize());
      PageHelper.orderBy("id desc");
      List<MyUser> myUsers = myUserServices.selectUser();
      PageBean<MyUser> pageBean = new PageBean<>(myUsers);
      return new ResponseResult<>(200, "success", pageBean);
    }

    代码看起来比较奇怪,只需要传递进来需要的当前页面数已经每页的大小就可以实现对mybatis的查询语句分页;另外还可以实现升序和降序。

    1. 它是如何办到的?是否使用了动态代理?
    2. 是通过sql实现分页吗?
    3. PageHelper.startPage()是不是使用了ThreadLocal?什么时候释放ThreadLocal里面的value?是否会造成ThreadLocal内存泄漏?

    带着这些问题我进行了源码分析,本文不介绍如何配置实现分页功能,代码可以从这里下载: https://github.com/pmh905001/freedom-20200203springboot

    主要还是探究PageHelper的实现原理,可以从这篇文章借鉴到源码分析的一些思路.

    入手

    如何入手分析PageHelper的实现原理呢?

    当前代码是controller--->service--->Mapper就简单几行代码是无法看到跟踪到内部实现的,排除此方法。

    它的代码里面既然设置了pageSize, PageHelper.startPage(pageModel.getPageNum(), pageModel.getPageSize());那么就一定有使用它的地方,我们顺着这个方法可以跟踪到这里

      

     PageHelper原理分析

     看到这里实际上回答我的第三个问题:PageHelper.startPage()是不是使用了ThreadLocal?是的,它是使用了ThreadLocal。

    那么我们就在我们就在PageSize这个字段做一个跟踪断点。我们可以得到如下调用栈:

     我们可以找到一个名为PageInterceptor的代理类对正在执行的mybatis SQL进行了拦截,首先查询的总数,然后在进行分页查询。 

    并且从下面的语句我们可以看出这个动态代理类拦截的是Executor类里面的query方法。

    分析到这里,实际上已经回答了我的第一个疑问 。

    1. 它是如何办到的?是否使用了动态代理?

    他是通过动态代理拦截了Executor.query()方法。而且他应该java自带的动态代理实现。

    通过分析PageInterceptor,我们同样可以回答问题2:

      2.是通过sql实现分页吗?

    是通过sql来实现分页的,这里不再详述。

     其他

    还有一个问题是我们看到了PageHelper是通过ThreadLocal来设置分页信息的,那么什么地方该来释放分页信息呢?否则有可能造成内存泄漏.

    PageHelper里面有一个clearPage()方法,反向查看调用点即可以知道程序在哪儿释放分页信息。

    从上面的代码可以看出,拦截器执行完毕之后最终会释放分页信息。并且放在finally块中,可以保证不会出现ThreadLocal内存泄漏。

    还有一个问题,Mybatis是否支持Executor多个拦截器,比如:分页拦截器和排序拦截器,答案是肯定的。Mybatis使用提供了一种插件的机制,读者可以参考一下InterceptorChain.pluginAll()方法。

     这里代码有点绕,我之前看到这里感觉很别扭,这应该只返回一个动态代理类,怎么会支持多层拦截呢? 实际上这里代码写的很精炼,每一次循环相当于被代理上面套了一层,第二次循环就会再在动态代理类基础上再封装一层.

  • 相关阅读:
    趣题:寻找出现了奇数次的数
    zstu2016校赛圣杯战争
    HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)
    HDU 5673 Robot ——(卡特兰数)
    HDU 3775 Chain Code ——(Pick定理)
    2016 ICPC北京站现场赛总结(再度流水账)
    2014苏州大学新生赛第二场(12.10)题目解析
    【Jump Game II 】cpp
    【Jump Game】cpp
    【 Sqrt(x) 】cpp
  • 原文地址:https://www.cnblogs.com/pmh905001/p/12286008.html
Copyright © 2020-2023  润新知