PageHelper分页原理
PageHelper上文说过是一个Mybatis的分页插件,使用起来很简单,今天就来看看它背后的原理。
1、先看startPage方法,这个先生成一个Page对象,先从本地线程ThreadLocal中获取,当已经执行过orderBy的时候,取出来orderby设置到新Page对象中,最后放到本地线程中。
startPage方法
2,上面说的Page,来看看是什么结构?
Page是实现Closeable接口,并且继承了ArrayList,并且定义一些分页用到的成员变量,比如页码,每页大小,总数等。后面会说通过拦截的查询返回的对象就是Page对象。
Page类
3,PageInterceptor类中的intercept方法,如果需要分页,就是通过查询总数,并按分页查询数据。在Mybatis的系列文章中说个Invocation对象,这个类就三个变量,一个是目标对象,一个是目标方法,最后就是方法中的参数数组。我们所需要的就是从Invocation中取出来对应的变量做逻辑处理。
intercept方法
3.1、PageInterceptor中的Dialect变量,这个可以配置到拦截器的属性中,如果不配置默认就是PageHelper类。
3.2、PageHelper的setProperties方法中会创建PageParams和PageAutoDialect实例,PageAutoDialect如果没有配置方言,会自动检查,如果配置helperDialect,会用配置的方言。
3.3、在PageInterceptor类的intercept方法中会判断是否分页,调用dialect.skip方法,默认调用PageHelper的skip方法。
3.4、skip方法中,会从PageParams中获取Page,如果获取不到就返回true,否则返回false,
skip方法
3.5、pageParams.getPage方法,会从ThreadLocal获取Page,如果取不到,判断RowBound是否DEFAULT,如果不是会从rowbound获取offset和limit生成一个Page对象。
3.6、如果需要分页,先判断是否需要执行count,如果需要就会count方法,来看看怎么做count的?
生成一个新的MappedStatemen的ID,会判断是否当前的sql是否执行count,如果不是就从缓存查看,如果没有就新建一个MappedStatemen。最后执行count操作。
count方法
3.7、执行count操作的是ExecutorUtil工具类的executeAutoCount方法。这个方法主要就是调用方言获取count sql,最后调用executor执行这个sql获得count数。
executeAutoCount方法
3.8、回来再看PageInterceptor的intecepts方法,如果需要分页,会执行ExecutorUtil的pageQuery分页查询方法。首先处理参数对象,再次通过方言获取分页的sql,最后执行分页sql。
pageQuery分页方法
3.9、最后把分页的结果封装为一个Page对象,如果没反应就直接返回。上篇文章说过,Page是继承于ArrayList,可以说Page就是个集合类。
afterpage方法
分页的逻辑就大概说完了,其实里面有很多细节的处理。
领取专属 10元无门槛券
私享最新 技术干货