再议分页插件PageHelper
1、问题描述
java分页以前介绍过pagehelper,最近项目中又用到分页,看了下,发现使用springboot下使用起来更加方便了,又系统看了看,分享下,希望能帮到有需要的朋友。
2、解决方案
2.1 官方文档
还是那句话,官方文档才是yyds,地址:https://github.com/pagehelper
第一个mybatis-pagehelper是源码实现,第二个springboot的是对第一个做了封装。
目前springboot下最新的pagehelper版本是:1.3.1
2.2 具体配置与使用
因为老王的代码是公司电脑上,复制不出来,本地简单弄了个案例说明下。
springboot下使用pagehelper更加方便了,只需要配置两个地方就可以了
2.2.1 pom文件
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
有了springboot下的pagehelper的gav,就不需要mybatis的gav了,pagehelper的gav中已经包含mybatis的gav了。
2.2.2 yml文件配置下
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
params: count=countSql
主要是配置下helper-dialect,这里是根据不同的配置,会使用不同的方言。
2.2.3 代码中运用
Page<TLaowang> page = PageHelper.startPage(info.getPageNum(), info.getPageSize());
List<TLaowang> list = tLaowangMapper.selectAll();
通过在待执行的mybatis的mppper前设置page,就可以达到分页的目的了。
2.2.4 重要提示
这里提到官网有个重要提示:
PageHelper.startPage方法重要提示
只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会被分页。
请不要配置多个分页插件
请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xml和Spring<bean>配置方式,请选择其中一种,不要同时配置多个分页插件)!
分页插件不支持带有for update语句的分页
对于带有for update的sql,会抛出运行时异常,对于这样的sql建议手动分页,毕竟这样的sql需要重视。
分页插件不支持嵌套结果映射
由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。
很重要的一点PageHelper.startPage要紧挨mybatis执行方法,网上查的原因,不保证真的准确。
PageHelper方法使用了静态的ThreadLocal参数,分页参数和线程是绑定的。内部流程是ThreadLocal中设置了分页参数(pageIndex,pageSize),之后在查询执行的时候,获取当线程中的分页参数,执行查询的时候通过拦截器在sql语句中添加分页参数,之后实现分页查询,查询结束后在 finally 语句中清除ThreadLocal中的查询参数
源码:
3、代码验证
3.1 分层代码
(1)cotroller
@RequestMapping(value ="/selectAll", method = RequestMethod.POST)
public Object select(LPageInfo info) {
return testService.selectAll(info);
}
(2)service
public List<TLaowang> selectAll(LPageInfo info) {
Page<TLaowang> page = PageHelper.startPage(info.getPageNum(), info.getPageSize());
List<TLaowang> list = tLaowangMapper.selectAll();
// PageInfo pageInfo = new PageInfo(list);
// System.out.println(pageInfo.getTotal());
System.out.println(page.getTotal());
return list;
}
简要说明:
这里两个说明,一是tLaowangMapper要紧跟PageHelper;二是total页码,可以通过page获取,也可以通过PageInfo获取,另外会出现跨service获取total页码丢失的情况,要特别注意位置问题。
(3)mapper
<select id="selectAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_laowang
</select>
(4)测试数据
3.2 执行效果
3.2.1 swagger执行
pagenum=3,pagesize=3
3.2.2 debug看效果
从debug效果看,list已经是page类型了,返回3条数据,数据是从第7条到第9条,total是9条。
3.2.3 通过idea插件mybatis-log查看数据库执行sql
说明:
(1)从图中不难看出,pagehelper执行了两条sql,一条获取total总数,二是调用mysql的分页语句进行分页。
mysql分页语句:
select * from table limit (start-1)*pageSize,pageSize;
其中start是页码,pageSize是每页显示的条数。
查询第1条到第10条的数据的sql是:select * from table limit 0,10;
->对应我们的需求就是查询第一页的数据:select * from table limit (1-1)*10,10;
例如:select * from table limit 0,10; --从第0条开始,查询10条数据。
select * from table limit 10,10; --从第10条开始,查询10条数据。
(2)分页pagenum是从1开始的。
4、总结
简单来说,pagehelper是通过封装拦截,将分页拼接到待执行sql中,起到分页的效果,底层还是使用的对应数据的分页语句,因为不同的数据库分页语句不一样,所以才需要配置数据库类型,拼接不同的分页语句到待执行sql中去。
更多信息请关注公众号:「软件老王」,关注不迷路,软件老王和他的IT朋友们,分享一些他们的技术见解和生活故事。