时隔8个月,分页插件这次带来了一次大的更新。
5.2.0 - 2020-07-26
-
jsqlparser升级到3.2版本,sql解析更好,对sqlserver支持更好。
-
修改 sqlserver 方式中的替换正则,现在允许 with( nolock ) 括号中存在空格。
-
解决 reasonable 和 pageSizeZero,以及 offset 用法中的bug,现在的含义和结果更一致。
-
分页 SQL 拼接过程中增加换行符,避免原始 SQL 中存在注释导致分页部分无效。
-
Oracle 和 Db2 中的行号 ROW_ID 别名改为 PAGEHELPER_ROW_ID,避免和常用名称冲突。
-
解决单个参数ProviderSql使用其他拦截器时的特殊问题(支持 mybatis 3.4.0+)by 罗震宇
-
支持自动识别 clickhouse,使用 MySQL 方式进行分页。
-
将 startRow, endRow 类型从 int 改为 long。
-
Page 增加 public <T> PageInfo<T> toPageInfo(Function<E, T> function) 方法,用于转换查询结果中的数据。
-
参考 pr#476 提供 ·Oracle9iDialect`,这也是曾经用过的一种分页方式,可以自己测试选择合适的分页方式。
目前提供的两种 Oracle 分页如下:
-- OracleDialect 外层控制范围
WHERE ROW_ID <= ? AND ROW_ID > ?
-- Oracle9iDialect 内外分别控制范围
TMP_PAGE WHERE ROWNUM <= ? ) WHERE ROW_ID > ?
-
增加分页插件的 BoundSqlInterceptor 拦截器,可以在3个阶段对 SQL 进行处理或者简单读取, 增加参数 boundSqlInterceptors,可以配置多个实现 BoundSqlInterceptor 接口的实现类名, 使用英文逗号隔开。PageHelper调用时,也可以通过类似 PageHelper.startPage(x,x).boundSqlInterceptor(BoundSqlInterceptor boundSqlInterceptor)针对本次分页进行设置。
本次更新最大的变化是增加了 BoundSqlInterceptor,通过该接口可以在运行时拦截分页处理的 SQL(BoundSQL对象):
/**
* BoundSql 处理器
*/
public interface BoundSqlInterceptor {
/**
* boundsql 处理
*
* @param type 类型
* @param boundSql 当前类型的 boundSql
* @param cacheKey 缓存 key
* @param chain 处理器链,通过 chain.doBoundSql 方法继续执行后续方法,也可以直接返回 boundSql 终止后续方法的执行
* @return 允许修改 boundSql 并返回修改后的
*/
BoundSql boundSql(Type type, BoundSql boundSql, CacheKey cacheKey, Chain chain);
enum Type {
/**
* 原始SQL,分页插件执行前,先执行这个类型
*/
ORIGINAL,
/**
* count SQL,第二个执行这里
*/
COUNT_SQL,
/**
* 分页 SQL,最后执行这里
*/
PAGE_SQL
}
/**
* 处理器链,可以控制是否继续执行
*/
interface Chain {
Chain DO_NOTHING = new Chain() {
@Override
public BoundSql doBoundSql(Type type, BoundSql boundSql, CacheKey cacheKey) {
return boundSql;
}
};
BoundSql doBoundSql(Type type, BoundSql boundSql, CacheKey cacheKey);
}
}
接口中包含了 boundSql 接口方法,还有 Type 枚举,和 Chain 接口的定义,自己实现的时候不需要考虑 Chain。
通过 boundSqlInterceptors 参数配置拦截器,执行时存在下面三种情况:
-
不管当前执行的 SQL 是否会分页,都会执行 Type.ORIGINAL 类型的拦截器方法,配置后一定会执行。
-
调用分页方法时,拦截器会继续执行 Type.COUNT_SQL 类型的拦截器方法,这个方法只有执行分页并且指定要进行 count 查询时才会执行。
-
调用分页方法时,如果 count > 0,就会执行 Type.PAGE_SQL 类型的拦截器方法,这个方法只有执行分页时才会执行。
通过 PageHelper.startPage(1, Integer.MAX_VALUE, false).boundSqlInterceptor(BoundSqlInterceptor boundSqlInterceptor) 这种指定的参数时,也能起到不进行分页和count查询,但是可以执行 Type.ORIGINAL 类型的拦截器方法。
当前拦截器在整个分页执行过程中,会执行3次,对应 Type 枚举的 3 个类型,执行顺序也一致。
如果想获取分页 SQL 执行前的,只需要关注 Type.ORIGINAL,另外两种就是 count 执行前和分页执行前(count=0时分页方法不执行,这里也不会执行)。
以测试代码为例:
public class TestBoundSqlInterceptor implements BoundSqlInterceptor {
public static final String COMMENT = "\n /* TestBoundSqlInterceptor */\n";
@Override
public BoundSql boundSql(Type type, BoundSql boundSql, CacheKey cacheKey, Chain chain) {
if (type == Type.ORIGINAL) {
String sql = boundSql.getSql();
MetaObject metaObject = MetaObjectUtil.forObject(boundSql);
metaObject.setValue("sql", sql + COMMENT);
}
return chain.doBoundSql(type, boundSql, cacheKey);
}
}
上面这段代码在 sql 执行前先修改原始 SQL,只是在最后增加了一段注释,不影响 SQL 执行,通过下面的方式配置:
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 支持通过Mapper接口参数来传递分页参数 -->
<property name="helperDialect" value="mysql"/>
<property name="boundSqlInterceptors"
value="com.github.pagehelper.test.basic.provider.TestBoundSqlInterceptor,com.github.pagehelper.test.basic.provider.TestBoundSqlInterceptor"/>
</plugin>
这里为了说明该参数值可以是多个,因此重复配置了一次,也就是上面的拦截器会执行两次。
这样配置后,上面的 SQL 在分页执行的时候就会修改 SQL。
除了这种配置方式外,还支持 PageHelper.startPage 时临时指定,这种方式会把拦截器放到链头先执行,因此可以控制后续的是否执行,也可以在后续所有执行外,做最后处理再返回。
示例:
PageHelper.startPage(1, 10).boundSqlInterceptor(new BoundSqlInterceptor() {
@Override
public BoundSql boundSql(Type type, BoundSql boundSql, CacheKey cacheKey, Chain chain) {
System.out.println("before: " + boundSql.getSql());
BoundSql doBoundSql = chain.doBoundSql(type, boundSql, cacheKey);
System.out.println("after: " + doBoundSql.getSql());
if (type == Type.ORIGINAL) {
Assert.assertTrue(doBoundSql.getSql().contains(TestBoundSqlInterceptor.COMMENT));
}
return doBoundSql;
}
});
pagehelper-spring-boot-starter
在 pom.xml 中添加如下依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
v1.3.0 - 2020-07-26
- 升级 PageHelper 到 5.2.0,包含大量改动
- 升级 MyBatis 到 3.5.5
- 升级 MyBatis Starter 到 2.1.3
- 升级 springboot 到 2.3.1.RELEASE
PageHelperAutoConfiguration 增加 @Lazy(false) 注解,当配置延迟加载时,避免分页插件出错
- 添加分页插件时判断是否已经配置过同一个实例(不同的配置是不同的实例)