https://ost.51cto.com/posts/18522

简单来说就是通过 MyBatis 的拦截器和插件实现的,PageHelper 实现了 Interceptor 拦截器接口,并拦截 Executor 的 query 方法,在执行前PageHelper会在原始 SQL 前拼装分页相关的SQL。

用法

此时 commentAnalyses 为 Page 对象(PageHelper 插件包内定义的)

https://dl-harmonyos.51cto.com/images/202210/386a924712af31d95ce586ce7efdb8f4b3e339.png

而 Page 对象继承自 JDK 中的 ArrayList,扩展并封装了一些 page 相关的字段,如页码,每页大小,总记录数,总页数等。

原理

我们就加了一行,它是如何帮助我们实现分页的呢?请往下看。

PageHelper.startPage 做了什么

我们看这一行 PageHelper.startPage(pageIndex, pageSize);做了什么。这个类中重载了好多个 startPage 方法,最终调用到如下的一个方法

可以看到该方法将分页信息作为构造器参数实例化 Page 对象,调用 SqlUtil.getLocalPage()获取一个旧的 Page 对象,最后调用 SqlUtil.setLocalPage(page);把新创建的 Page 对象 set 进去。

我们看看这两个方法做了什么。如下,很简单,从 ThreadLocal 中获取 Page 对象,将 Page 对象 set 到 ThreadLocal 中。知道 ThreadLocal 作用的不用多说,不知道的可以理解为用于保存本地变量,并与线程绑定。

看到这我们暂且将这一行的作用记为,创建并保存 Page 对象(分页信息)到 ThreadLocal 中。

Page 分页信息在哪使用

那么既然保存了,就有使用的地方。

我通过代码追踪的方式定位到被调用的地方,通过回溯,发现是从这个类 com.github.pagehelper.dialect.AbstractDialect 发起调用的

https://dl-harmonyos.51cto.com/images/202210/5657e39842faa299853498067f1bbed24534dd.png