再议分页插件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朋友们,分享一些他们的技术见解和生活故事。

posted @ 2021-08-04 16:39  软件老王  阅读(318)  评论(0编辑  收藏  举报