PageHelper
PageHelper
是常用的分页插件,之前只停留在用的阶段,直到.......
发生了一次生产事故
所以准备把他的源码研究一下,看下原因
介绍(What)
从这里看到,PageHelper
的使用是建立在Mybatis
基础之上的,具体实现后面再说。 同时支持常见的各种数据库如 Mysql、Oracle、H2等,基本都能支持。
使用(How)
重要提示
PageHelper.startPag方法重要提示:
只有紧跟在PageHelper.startPage
方法后的第一个Mybatis的查询(Select)方法会被分页。
请不要配置多个分页插件
请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xml
和Spring<bean>
配置方式,请选择其中一种,不要同时配置多个分页插件)!
分页插件不支持带有for update语句的分页
对于带有for update
的sql,会抛出运行时异常,对于这样的sql建议手动分页,毕竟这样的sql需要重视。
分页插件不支持嵌套结果映射
由于嵌套结果方式会导致结果集折叠,因此分页查询的结果折叠后总数会减少,所以无法保证分页结果数量正确。
初步怀疑我的问题是这一步引起,因为我是联表查询
1. 引入Maven依赖
2. 配置拦截器
分页插件的使用是建立在 Mybatis拦截器上的,执行sql前会进行参数拼接
在 MyBatis 配置 xml 中配置拦截器插件
3. 使用
最常见的用法
原理(Why)
今天就来对源码一探究竟
PageHelper
从这个类开始
我们点进去看看
流程就是新建一个Page类,主要给SqlUtil设置 LocalPage()
, 看下LocalPage()实现
是一个线程私有的 ThreadLocal,这个方法到此结束。
那么,设置完这个,还不知道怎么执行分页的。我们再回到PageHelper
怎么生效的
回到PageHelper后,我们看到 pageHelper 实现了 mybatis的拦截器
那么可以断言,在Mybatis执行的时候,PageHelper通过拦截器做了些工作,我们来看 pageHelper中的intercept
方法
注释非常清晰,核心是 sqlUtil.processPage
方法,继续看
继续看 _processPage()
图中1是指:
supportMethodsArguments
:支持通过 Mapper 接口参数来传递分页参数,默认值false
,分页插件会从查询方法的参数值中,自动根据上面params
配置的字段中取值,查找到合适的值时就会自动分页。
2是真正处理的方法,我们放他出来, 比较长,但是耐心看看。
先查判断是否查总数,具体是通过page.isCount(), 这个参数我们在前面默认设置为true,
最后将执行的结果放进Page,page也是 ArrayList
题外
这里注意下
这个方法使用了桥接模式,抽象类实现了基本的方法
每个数据库继承了此类,实现了自己的方法
我们来看下 MysqlParser
主要是设置参数,和分页查询sql。
小节
PageHelper的原理主要是 mybatis拦截器
查总数用 select count(0) from ( 自己的sql)
分页用 select ---- limit ?,? 实现分页
后面放到 PageInfo里面去
版权声明: 本文为 InfoQ 作者【BitSea】的原创文章。
原文链接:【http://xie.infoq.cn/article/e711af70c0bd70bdf0b32aff6】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论