PageHelper


背景

上周写了一篇分享文,有大佬回复介绍了一个开源的PageHelper工具,就去了解学习了一下

简单介绍

首先甩出一个GitHub链接Mybatis-PageHelper

简单地看了一下源码,其实实际的原理是一样的,自定义了一个分页的拦截器,不过PageHelper拦截的方法是Executor.class中的query方法。

观察源码会发现,与我之前那篇文章中的实现相比,不同的是,PageHelper在完成了select count(1)即计数的功能之后,对于原sql的分页查询,全部在Interceptor中完成了,而不是在select count(1)之后,修改原sql,继续由invocation.proceed()来执行:

1
2
3
4
5
6
7
8
9
// PageInterceptor第113行,查询数量
count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler);

// PageInterceptor第135行
//执行分页
resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);

// 对查询出来的结果进行处理,转换为自定义的Page对象
return dialect.afterPage(resultList, parameter, rowBounds);

这样做的好处就是可以在sql查询完成之后,继续对返回的List进行处理,例如PageHelper在afterPage方法中做的就是讲返回的List对象中的数据取出,放到Page对象中(Page是继承自List的类,其中增加了pageNum、pageSize、total之类的属性)

示例

首先还是要给sqlSessionFactoryBean注册plugin,不过这一次不能直接在SQLSessionFactoryBean中写入了,因为PageInterceptor需要通过setProperties(Properties properties)方法初始化dialect,如果直接在application-database中通过标签向Spring注册bean,那么这个方法就不会被调用,导致后续的NullPoint异常。

正确的方式是,通过mybatis的config.xml注册plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 错误方式
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis/config.xml"/>
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor"/>
</array>
</property>
</bean>

// 正确方式
在SQLSessionFactoryBean中引入的config.xml中加入:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

接下来,只要在需要使用分页的地方先写一次分页参数:

PageHelper.startPage(1, 5);

然后继续执行dao方法,就可以完成分页:

List<String> testList = sampleDao.listTitle(4281);

此处虽然我是使用List来接受的结果,实际上这是一个Page对象,若想要获得total、pageNum、pageSize等信息,可以直接用Page来接受结果,或者用PageInfo对象来转换结果:

Page<String> testList = sampleDao.listTitle(4281);
PageInfo<String> pageInfo = new PageInfo<>(stringList);

结论

总体而言,PageHelper确实比自己造一个轮子要方便实用的多。

再写两个遇到的坑…

  • 引入PageHelper的时候要注意版本,貌似5.0.0之前的版本,拦截器的类是PageHelper,进入5.0.0之后变为了PageInterceptor
  • 5.0.0之前,注册plugin时要指定dialect,即加入一个参数;现在是不要指定dialect,会默认指定一个通用的,如果自己写很容易写错,例如我测试时写了一个MySqlDialect,结果这个东西并不是这么用的
-------------本文结束感谢您的阅读-------------
0%