PageHelper的使用及底层原理
业务系统在spring项目中引入 PageHelper 来实现分页方案,在实际使用过程中,发现在对 Mysql 数据库进行查询时,每条语句的末尾都自动拼接上了limit子句,且每次查询会先执行一次“select count(0)…”语句,与预期不符,因此想探究一下 PageHelper 的底层原理。
一、PageHelper的使用
PageHelper 是国内非常优秀的一款开源 mybatis 分页插件,它支持常用的主流数据库,例如 Oracle、Mysql、MariaDB、SQLite、Hsqldb 等。
PageHelper 的安装很简单,只需要在 pom.xml 中加入以下依赖即可:
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId></dependency>
PageHelper 的使用也非常简单,只需要在查询之前调 PageHelper.startPage() 方法即可开始分页。例如:
public PageInfo<BusinessPO> businessList(BusinessQuery businessQuery) {//开始分页PageHelper.startPage(pageNum, pageSize);//查询QueryWrapper<BusinessPO> queryWrapper = generateQuery(businessQuery);List<BusinessPO> businessPOS = businessMapper.selectList(queryWrapper);//封装分页对象PageInfoPageInfo<BusinessPO> pageInfo = new PageInfo<>(businessPOS);return pageInfo;}
其中,pageNum
表示要查询的页码
,pageSize
表示每页的记录数
。调用 startPage 方法之后,PageHelper 会自动将下一次查询作为分页查询,并且会在查询之后返回一个 Page 对象,然后可以将这个对象转换为 PageInfo 对象,从而获得分页相关的信息。
二、PageHelper的底层原理
首先调用 PageHelper 的 startPage 方法开启分页,方法中会将分页参数存到一个变量 ThreadLocal LOCAL_PAGE中;
然后调用 mapper 进行查询,这里实际上会被 PageInterceptor 类拦截,执行其重写的 interceptor 方法,该方法中主要做了以下两件事:
获取到 MappedStatement,拿到业务写好的 sql,将 sql 改造成 select count(0) 并执行查询,并将执行结果存到 LOCAL_PAGE 里的Page 中的 total 属性,表示总条数
获取到 xml 中的 sql 语句,并 append 一些分页 sql 段,然后执行,将执行结果存到 LOCAL_PAGE 里的 Page 中的 list 属性,这里的Page 类实际是 ArrayList 的子类。
可以看出,结果是封装到了 Page 中,最后交由 PageInfo,从中可以获取到总条数、总页数等参数。