- 发布6.1.0,PageHelper 提供 jsqlparser直接依赖都是中间接口,可以通过SPI替换默认实现
- 升级jsqlparser版本4.7,重新实现order by,分页,count查询
- 简化pom.xml配置,去掉shade内嵌jsqlparser方式,改为通过外部依赖选择不同的jsqlparser版本,允许自己SPI扩展
- jsqlparser解析不使用线程池,支持SPI扩展覆盖SqlParser实现
- SqlServer分页改为SqlServerSqlParser接口,添加参数 sqlServerSqlParser 覆盖默认值
- OrderByParser提取OrderBySqlParser接口,增加 orderBySqlParser 参数,可以覆盖默认实现
- OrderByParser静态方法改为普通方法,为后续改接口做准备
- jdk8+后不再需要JSqlParser接口,移除该接口,文档标记该参数(该参数早期用于支持sqlserver特殊配置) 兼容jsqlparser4.7版本
- maven-compiler-plugin固定版本以去除警告,并增加构建稳定性 qxo
- gitignore .vscode for vscode ide qxo
- 修改bug #779 chenyuehui
为了兼容 jsqlparser 4.5 和 4.7,以及后续可能存在的其他版本,新建了一个 pagehelper-sqlparser 项目,目前提供了 4.5 和 4.7 两个实现, 使用时从 pagehelper 排除 jsqlparser,然后选择一个 jsqlparser 实现即可,当前版本默认使用的 4.7 版本的代码, 因此如果想换 4.5 的实现,可以按照下面方式进行配置:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>6.1.0</version>
<exclusions>
<exclusion>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>sqlparser4.5</artifactId>
<version>6.1.0</version>
</dependency>
SPI 替换默认值的优先级低于 sqlServerSqlParser
,orderBySqlParser
,countSqlParser
参数指定的实现,不指定时如果存在SPI实现,即可生效,
SPI 可以参考 pagehelper-sqlsource 模块代码。
JSqlParser 默认解析 SQL 会使用临时创建的 Executors.newSingleThreadExecutor()
,这里通过 API 跳过了线程池:
CCJSqlParser parser = CCJSqlParserUtil.newParser(statementReader);
parser.withSquareBracketQuotation(true);
return parser.Statement();
JSqlParser 使用线程池的目的是为了防止解析超时,因此如果你遇到过超时的情况,可以引入下面的依赖(通过SPI覆盖了默认实现,超时时间10秒):
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>sqlparser-timeout</artifactId>
<version>6.1.0</version>
</dependency>
- 基于jdk8适配,6.0开始不支持jdk6和7,如果有需要可以使用5.x版本
- 增加异步count支持,全局配置
asyncCount
,默认false
,单次设置:PageHelper.startPage(1, 10).enableAsyncCount()
; 异步使用独立连接(事务)查询,有增删改操作影响查询时不适合开启异步查询。closed #334 - JSqlParser默认开启
parser.withSquareBracketQuotation(true)
,支持 SqlServer[]
- feat: 在
PageInfo
类中新增了用以进行数据对象转换的方法<E> PageInfo<E> convert(Page.Function<T, E> function)
by codeke CountSqlParser
改为接口,允许通过countSqlParser
参数替换为自己的实现,支持 #772dialectAlias
支持简化配置,例如dm=oracle;oracle=oracle9i
,直接引用现在的缩写,不用写类全名countColumn
添加注入检测,fixed #686- 增加
PageParam
类,不内嵌对象(会影响使用),如果想用可以继承该对象,closed #562 - 所有异常信息改为英文提示
- 放开
setLocalPage
,支持 #771 - 解决
sqlserver
带union sql解析时处理order by错误的问题,fixed #768 - 优化total逻辑,解决指定不分页查询,同时指定order by时无效的问题,fixed #641
- 修改 dialect 实例化逻辑,保证类完成配置后使用,fixed #742
dialectAliasMap
改为LinkedHashMap
,可以按配置顺序进行匹配,fixed #758- 行云数据库分页BUG修复 by maimaitiyaer_bonc
- Ignoring unnecessarily generated surefire-report by java-codehunger
- 支持从URL中解析openGauss 数据库 对应的方言 by saxisuer
- 修复sql注入检验不正确问题 #716 by uyong
- 支持从url中解析人大金仓kingbase8对应的方言 by univ
- 添加支持cirrodata的分页 #705 by sxh0570
- 使用文档更新,所有参数都包含在内,首页默认文档改为中文。
- Add support for kingbase. by HanHuimin001
- 增加
debug
参数,默认false
,为true
时开启debug
模式,开始debug
模式后将记录调用堆栈 by huyingqian - Add 支持count的sql支持hint语法 by zhanliquan
- 增加
PageProperties
接口,框架内部实例化的扩展类如果实现了这个接口,可以通过这个接口的方法获取分页插件配置。 - 增加
CountMsIdGen
接口,可以通过countMsIdGen
配置自定义实现类,该类用于生成查询对应COUNT查询的msId。默认实现还是使用countSuffix
,通过扩展可以实现如selectByExample
映射到对应的selectCountByExample
方法。 - 增加
keepOrderBy
和keepSubSelectOrderBy
配置。 - 增加
sqlParser
配置,增加JSqlParser
接口,解决 jsqlparser 和 jdk 兼容性导致无法额外配置的问题(**6.1.0 移除该参数 **)。 - 测试使用 logback 日志框架,去掉log4j。
- 解决
dialectKey
为空导致NPE,fixed #656
关于以上参数的详细介绍,请查看 如何使用分页插件。
- 处理 CVE-2022-28111 漏洞,限制 order by 参数,避免 SQL 注入
- Add support for as400. by bluezealot
- 优化分页结果包装类的泛型参数 by 章福来
- 规范PostgreSQL分页参数的顺序 by outian
- 增加
AutoDialect
接口用于自动获取数据库类型,可以通过autoDialectClass
配置为自己的实现类,默认使用DataSourceNegotiationAutoDialect
,优先根据连接池获取。 默认实现中,增加针对hikari,druid,tomcat-jdbc,c3p0,dbcp
类型数据库连接池的特殊处理,直接从配置获取jdbcUrl,当使用其他类型数据源时,仍然使用旧的方式获取连接在读取jdbcUrl。 想要使用和旧版本完全相同方式时,可以配置autoDialectClass=old
。当数据库连接池类型非常明确时,建议配置为具体值,例如使用 hikari 时,配置autoDialectClass=hikari
,使用其他连接池时,配置为自己的实现类。 - 支持运行时动态指定使用的 dialect 实现,例如
PageHelper.startPage(1, 10).using("oracle");
或者PageHelper.startPage(2, 10).using("org.exmaple.CustomDialect");
PageInfo
增加空实例常量属性PageInfo.EMPTY
以及内容判断boolean hasContent()
。- 启动中增加 banner, 需要日志级别 debug,可以通过
-Dpagehelper.banner=false
或者环境变量PAGEHELPER_BANNER=false
关闭增加 banner 的目的在于,如果你配置了多次分页插件,你会看到 banner 输出多次,你可以在DEBUG [main] - ,------. ,--. ,--. ,--. | .--. ' ,--,--. ,---. ,---. | '--' | ,---. | | ,---. ,---. ,--.--. | '--' | ' ,-. | | .-. | | .-. : | .--. | | .-. : | | | .-. | | .-. : | .--' | | --' \ '-' | ' '-' ' \ --. | | | | \ --. | | | '-' ' \ --. | | `--' `--`--' .`- / `----' `--' `--' `----' `--' | |-' `----' `--' `---' `--' is intercepting.
PageInterceptor
构造方法断点看看那些地方进行了实例化。 - 完善 Count 查询,当存在 having 时,不在优化查询列。查询列存在有别名的函数或者运算时也不优化查询列,避免 order by 或 having 中使用的别名不存在。
- 增加判断处理某些数据(如 TDEngine)查询 count 无结果时返回 null
- 添加 Firebird 数据库支持和 SqlServer2012 分页语法相同。
- 添加 impala 数据库自动识别。
- JSqlParser 升级为 4.2 版本。
距离上次更新3个月左右,这次更新直接让假期少了3天 🏃 ,关了 GitHub 和 Gitee 上的 200 多个issue,不一定所有问题都得到了处理,如果你还有疑问,可以继续提 issue,下个大版本会考虑直接 6.0,计划全部升级到 java 8,功能保持不变。
- 升级依赖 jsqlparser 4.0, mybatis 3.5.7
- 自动识别以下数据库:
- 虚谷数据库 xugu #599
- 神通数据库 oscar by ranqing
- 瀚高数据库 highgo by ashaiqing
- BoundSqlInterceptorChain拦截器index参数bug, fixed #587
- fixed #558
- 添加 PostgreSQL 方言 by liym@home
- fixed #604, 解决total丢失的问题
- 规范注释, fixed #547
-
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;
}
});
- 增加神通数据库的支持 wangss
- Add support for HerdDB - support HerdDB, mostly like MySQL - auto detect HerdDB Enrico Olivelli
- fix some typos and grammar issues LHearen
在 5.1.0 - 2017-08-28 版本中,增加 ReplaceSql
接口用于处理 sqlServer 的 with(nolock)
问题,增加了针对性的 replaceSql
参数,
可选值为 simple
和 regex
,或者是实现了ReplaceSql接口的全限定类名。默认值为 simple
,仍然使用原来的方式处理,
新的 regex
会将如 table with(nolock)
处理为 table_PAGEWITHNOLOCK
。
本次更新仅仅是把默认值从 simple
改为了 regex
,使用 regex
方式几乎能 100% 解决 sqlServer 的分页问题。
下面是两个 issue 中的示例。
示例 SQL #76
原始 SQL:
SELECT *
FROM
forum_post_info a with(nolock)
LEFT JOIN forum_carcase_tags as b with(nolock) on a.id = b.carcase_id where b.tag_id = 127
转换的 Count SQL:
SELECT COUNT(0)
FROM forum_post_info a WITH (NOLOCK)
LEFT JOIN forum_carcase_tags b WITH (NOLOCK) ON a.id = b.carcase_id
WHERE b.tag_id = 127
转换的分页 SQL:
SELECT TOP 10 *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY RAND()) AS PAGE_ROW_NUMBER, *
FROM (
SELECT *
FROM forum_post_info a WITH (NOLOCK)
LEFT JOIN forum_carcase_tags b WITH (NOLOCK) ON a.id = b.carcase_id
WHERE b.tag_id = 127
) PAGE_TABLE_ALIAS
) PAGE_TABLE_ALIAS
WHERE PAGE_ROW_NUMBER > 1
ORDER BY PAGE_ROW_NUMBER
示例 SQL #398
原始 SQL:
Select AUS.ScheduleID, AUS.SystemID, AUS.ClinicID, AUS.DoctorID, AUS.ScheduleDate,
AUS.StartTime, AUS.EndTime, AUS.Status, AUS.BookBy, AUS.Note, AUS.Remark, AUS.SourceType, CM.CompanyName,
AU.UserName As DoctorName, AU.UserNumber As DoctorNumber, CC.CodeDesc As ClinicName, CD.Lat, CD.Lng,
CD.ContactTel, CD.Address, CR.ConsultationStatusID, CR.RegisterStatus,A1.CodeDesc as AreaLevel1, A2.CodeDesc as AreaLevel2
From ACM_User_Schedule AUS with(nolock)
Left Join Client_Register CR with(nolock) On AUS.BookBy=CR.ClientID And CR.SourceType='F' And AUS.ClientRegisterNum=CR.ClientRegisterNum
Inner Join ACM_User AU with(nolock) On AU.UserID = AUS.DoctorID
Inner Join Code_Clinic CC with(nolock) On AUS.ClinicID=CC.CodeID
Inner Join Clinic_Detail CD with(nolock) On CC.CodeID = CD.ClinicID
Inner Join Code_Area A1 with(nolock) On CD.AreaLevel1ID=A1.CodeID
Inner Join Code_Area A2 with(nolock) On CD.AreaLevel2ID=A2.CodeID
Inner Join Company_Master CM with(nolock) On CC.SystemID = CM.SystemID
Where BookBy=1
转换的 Count SQL:
SELECT COUNT(0)
FROM ACM_User_Schedule AUS WITH (NOLOCK)
LEFT JOIN Client_Register CR WITH (NOLOCK)
ON AUS.BookBy = CR.ClientID
AND CR.SourceType = 'F'
AND AUS.ClientRegisterNum = CR.ClientRegisterNum
INNER JOIN ACM_User AU WITH (NOLOCK) ON AU.UserID = AUS.DoctorID
INNER JOIN Code_Clinic CC WITH (NOLOCK) ON AUS.ClinicID = CC.CodeID
INNER JOIN Clinic_Detail CD WITH (NOLOCK) ON CC.CodeID = CD.ClinicID
INNER JOIN Code_Area A1 WITH (NOLOCK) ON CD.AreaLevel1ID = A1.CodeID
INNER JOIN Code_Area A2 WITH (NOLOCK) ON CD.AreaLevel2ID = A2.CodeID
INNER JOIN Company_Master CM WITH (NOLOCK) ON CC.SystemID = CM.SystemID
WHERE BookBy = 1
转换的分页 SQL:
SELECT TOP 10 ScheduleID, SystemID, ClinicID, DoctorID, ScheduleDate
, StartTime, EndTime, Status, BookBy, Note
, Remark, SourceType, CompanyName, DoctorName, DoctorNumber
, ClinicName, Lat, Lng, ContactTel, Address
, ConsultationStatusID, RegisterStatus, AreaLevel1, AreaLevel2
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY RAND()) AS PAGE_ROW_NUMBER, ScheduleID, SystemID, ClinicID, DoctorID
, ScheduleDate, StartTime, EndTime, Status, BookBy
, Note, Remark, SourceType, CompanyName, DoctorName
, DoctorNumber, ClinicName, Lat, Lng, ContactTel
, Address, ConsultationStatusID, RegisterStatus, AreaLevel1, AreaLevel2
FROM (
SELECT AUS.ScheduleID, AUS.SystemID, AUS.ClinicID, AUS.DoctorID, AUS.ScheduleDate
, AUS.StartTime, AUS.EndTime, AUS.Status, AUS.BookBy, AUS.Note
, AUS.Remark, AUS.SourceType, CM.CompanyName, AU.UserName AS DoctorName, AU.UserNumber AS DoctorNumber
, CC.CodeDesc AS ClinicName, CD.Lat, CD.Lng, CD.ContactTel, CD.Address
, CR.ConsultationStatusID, CR.RegisterStatus, A1.CodeDesc AS AreaLevel1, A2.CodeDesc AS AreaLevel2
FROM ACM_User_Schedule AUS WITH (NOLOCK)
LEFT JOIN Client_Register CR WITH (NOLOCK)
ON AUS.BookBy = CR.ClientID
AND CR.SourceType = 'F'
AND AUS.ClientRegisterNum = CR.ClientRegisterNum
INNER JOIN ACM_User AU WITH (NOLOCK) ON AU.UserID = AUS.DoctorID
INNER JOIN Code_Clinic CC WITH (NOLOCK) ON AUS.ClinicID = CC.CodeID
INNER JOIN Clinic_Detail CD WITH (NOLOCK) ON CC.CodeID = CD.ClinicID
INNER JOIN Code_Area A1 WITH (NOLOCK) ON CD.AreaLevel1ID = A1.CodeID
INNER JOIN Code_Area A2 WITH (NOLOCK) ON CD.AreaLevel2ID = A2.CodeID
INNER JOIN Company_Master CM WITH (NOLOCK) ON CC.SystemID = CM.SystemID
WHERE BookBy = 1
) PAGE_TABLE_ALIAS
) PAGE_TABLE_ALIAS
WHERE PAGE_ROW_NUMBER > 1
ORDER BY PAGE_ROW_NUMBER
SQL 经过 https://tool.oschina.net/codeformat/sql 格式化。
- 升级 jsqlparser 为 2.0,升级 mybatis 为 3.5.1,解决兼容性问题。
- 完善分页逻辑判断,fixed #389
- 解决 MetaObject 版本兼容性问题 fixed #349
- 处理 order by 解析失败时输出警告日志,不在抛出异常
- 解决三处可能会导致countColumn失效的问题 fixed #325
- 解决 BIT_ 少的逗号 fixed #341
- 处理文档中的失效链接 isea533
- 文档示例错误,fixed #366
- fixed #373 NPE 问题
- 增加对阿里云PPAS数据库的支持,自动识别edb,fixed #281
- 增加参数 useSqlserver2012,设置为 true 后,使用 sqlserver2012(Dialect) 作为 SqlServer 数据库的默认分页方式,这种情况在动态数据源时方便使用。默认使用的低版本(05,08)分页方式。
- 增加 IPage 接口,目前支持 mybatis 查询方法只有一个参数,并且参数实现 IPage 接口时,如果存在分页参数,就会自动进行分页查询。感谢 moonfruit 两年前的 issue。
- 解决 HashSet 并发问题 fixed #276
- 优化代码结构,精简拦截器代码
- 优化代码,去掉没必要的校验(by lenosp)
- 解决 pageKey 多处理一次的小问题 #268
- 新增 gitee 提供的 javadoc 文档(https://apidoc.gitee.com/free/Mybatis_PageHelper)
- 解决默认反射不带缓存的问题 fixed #275
- 优化mysql ifnull函数导致分页性能问题 (by miaogr)(这个修改最终改成了下面的
aggregateFunctions
) - jsqlparser 升级为 1.2 版本,和 1.0 有不兼容的情况,已经解决。 fixed 273
- 去掉 PageInfo 中存在歧义的 g(s)etFirstPage 和 g(s)etLastPage 两个方法
- 抛出排序时解析失败的异常 fixed #257
- 解决 Spring
<bean>
方式配置时,没有properties
属性时的初始化问题 fixed #26 - 修复Oracle分页会漏查数据的问题 (by muyun12)
- 新增
aggregateFunctions
参数(CountSqlParser
), 允许手动添加聚合函数(影响行数),所以以聚合函数开头的函数,在进行 count 转换时,会套一层。其他函数和列会被替换为 count(0),其中count列可以自己配置。
增加 aggregateFunctions
参数后,和原先最大的区别是,如果存在 select ifnull(xxx, yy) from table ...
,原先的 count 查询是
select count(0) from (select ifnull(xxx, yy) from table ...) temp_count
,现在会区别聚合函数,如果不是聚合函数,就会变成
select count(0) from table ...
。
默认包含的聚合函数前缀如下:
/**
* 聚合函数,以下列函数开头的都认为是聚合函数
*/
private static final Set<String> AGGREGATE_FUNCTIONS = new HashSet<String>(Arrays.asList(
("APPROX_COUNT_DISTINCT," +
"ARRAY_AGG," +
"AVG," +
"BIT_" +
//"BIT_AND," +
//"BIT_OR," +
//"BIT_XOR," +
"BOOL_," +
//"BOOL_AND," +
//"BOOL_OR," +
"CHECKSUM_AGG," +
"COLLECT," +
"CORR," +
//"CORR_," +
//"CORRELATION," +
"COUNT," +
//"COUNT_BIG," +
"COVAR," +
//"COVAR_POP," +
//"COVAR_SAMP," +
//"COVARIANCE," +
//"COVARIANCE_SAMP," +
"CUME_DIST," +
"DENSE_RANK," +
"EVERY," +
"FIRST," +
"GROUP," +
//"GROUP_CONCAT," +
//"GROUP_ID," +
//"GROUPING," +
//"GROUPING," +
//"GROUPING_ID," +
"JSON_," +
//"JSON_AGG," +
//"JSON_ARRAYAGG," +
//"JSON_OBJECT_AGG," +
//"JSON_OBJECTAGG," +
//"JSONB_AGG," +
//"JSONB_OBJECT_AGG," +
"LAST," +
"LISTAGG," +
"MAX," +
"MEDIAN," +
"MIN," +
"PERCENT_," +
//"PERCENT_RANK," +
//"PERCENTILE_CONT," +
//"PERCENTILE_DISC," +
"RANK," +
"REGR_," +
"SELECTIVITY," +
"STATS_," +
//"STATS_BINOMIAL_TEST," +
//"STATS_CROSSTAB," +
//"STATS_F_TEST," +
//"STATS_KS_TEST," +
//"STATS_MODE," +
//"STATS_MW_TEST," +
//"STATS_ONE_WAY_ANOVA," +
//"STATS_T_TEST_*," +
//"STATS_WSR_TEST," +
"STD," +
//"STDDEV," +
//"STDDEV_POP," +
//"STDDEV_SAMP," +
//"STDDEV_SAMP," +
//"STDEV," +
//"STDEVP," +
"STRING_AGG," +
"SUM," +
"SYS_OP_ZONE_ID," +
"SYS_XMLAGG," +
"VAR," +
//"VAR_POP," +
//"VAR_SAMP," +
//"VARIANCE," +
//"VARIANCE_SAMP," +
//"VARP," +
"XMLAGG").split(",")));
- 默认增加达梦数据库(dm),可以自动根据 jdbcurl 使用Oracle方式进行分页。如果想换 SqlServer 可以参考 5.1.3 更新日志中的
dialectAlias
参数。
Page
的toString
方法增加super.toString()
。最终输出形式如Page{属性}[集合]
。- 增加
defaultCount
参数,用于控制默认不带 count 查询的方法中,是否执行 count 查询,默认 true 会执行 count 查询,这是一个全局生效的参数,多数据源时也是统一的行为。 - 增加
dialectAlias
参数,允许配置自定义实现的 别名,可以用于根据 JDBCURL 自动获取对应实现,允许通过此种方式覆盖已有的实现,配置示例如(多个时分号隔开):<property name="dialectAlias" value="oracle=com.github.pagehelper.dialect.helper.OracleDialect"/>
- 增加
PageSerializable
,简化版的PageInfo
类,不需要那么多信息时,推荐使用或者参考这个类实现。
- 解决单独使用
PageHelper.orderBy
方法时的问题 #110;
- 此次更新解决的问题只和 SqlServer 2005,2008 有关
- 解决
RegexWithNolockReplaceSql
中正则w?
错误的问题,应该是w+
。 - 解决
SqlServerDialect
中没有初始化默认SimpleWithNolockReplaceSql
的错误。 SqlServerRowBoundsDialect
增加对replaceSql
参数的支持。
- 增加 4.x 以前版本包含的排序功能,用法一致(PageHelper增加了几个排序相关的方法)。
- 分页 SQL 转换为预编译 SQL。
- 增加
ReplaceSql
接口用于处理 sqlServer 的with(nolock)
问题,增加了针对性的replaceSql
参数,可选值为simple
和regex
,或者是实现了ReplaceSql接口的全限定类名。默认值为simple
,仍然使用原来的方式处理,新的regex
会将如table with(nolock)
处理为table_PAGEWITHNOLOCK
。 PageRowBounds
增加count
属性,可以控制是否进行count
查询。
- 增加
ReplaceSql
接口用于处理 sqlServer 的with(nolock)
问题,增加了针对性的replaceSql
参数,可选值为simple
和regex
,或者是实现了ReplaceSql接口的全限定类名。默认值为simple
,仍然使用原来的方式处理,新的regex
会将如table with(nolock)
处理为table_PAGEWITHNOLOCK
。
- 增加 4.x 以前版本包含的排序功能,用法一致(PageHelper增加了几个排序相关的方法)。
- 分页 SQL 转换为预编译 SQL。
- 增加对
Phoenix
数据库的简单配置支持,配置helperDialect=phoenix
即可,也可以自动识别Phoenix
数据库的 jdbc url。 - count 查询的缓存
msCountMap
key 改为String
类型,key 为 count 查询的MappedStatement
的 id。 - 增加
countSuffix
count 查询后缀配置参数,该参数是针对PageInterceptor
配置的,默认值为_COUNT
。 - 增加手写 count 查询支持,详情看下面介绍。
增加 countSuffix
count 查询后缀配置参数,该参数是针对 PageInterceptor
配置的,默认值为 _COUNT
。
分页插件会优先通过当前查询的 msId + countSuffix
查找手写的分页查询。
如果存在就使用手写的 count 查询,如果不存在,仍然使用之前的方式自动创建 count 查询。
例如,如果存在下面两个查询:
<select id="selectLeftjoin" resultType="com.github.pagehelper.model.User">
select a.id,b.name,a.py from user a
left join user b on a.id = b.id
order by a.id
</select>
<select id="selectLeftjoin_COUNT" resultType="Long">
select count(distinct a.id) from user a
left join user b on a.id = b.id
</select>
上面的 countSuffix
使用的默认值 _COUNT
,分页插件会自动获取到 selectLeftjoin_COUNT
查询,这个查询需要自己保证结果数正确。
返回值的类型必须是resultType="Long"
,入参使用的和 selectLeftjoin
查询相同的参数,所以在 SQL 中要按照 selectLeftjoin
的入参来使用。
因为 selectLeftjoin_COUNT
方法是自动调用的,所以不需要在接口提供相应的方法,如果需要单独调用,也可以提供。
上面方法执行输出的部分日志如下:
DEBUG [main] - ==> Preparing: select count(distinct a.id) from user a left join user b on a.id = b.id
DEBUG [main] - ==> Parameters:
TRACE [main] - <== Columns: C1
TRACE [main] - <== Row: 183
DEBUG [main] - <== Total: 1
DEBUG [main] - Cache Hit Ratio [com.github.pagehelper.mapper.CountryMapper]: 0.0
DEBUG [main] - ==> Preparing: select a.id,b.name,a.py from user a left join user b on a.id = b.id order by a.id LIMIT 10
DEBUG [main] - ==> Parameters:
TRACE [main] - <== Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE [main] - <== Row: 1, Angola, AO
TRACE [main] - <== Row: 2, Afghanistan, AF
TRACE [main] - <== Row: 3, Albania, AL
- 解决
supportMethodsArguments
参数不起作用的问题,由于之前默认为false
,不起作用后效果为true
,建议升级到最新版本。
Page<E>
继承Closeable
接口,在 JDK7+中可以使用try()
方式调用,自动调用PageHelper.clearPage();
#58。- 解决:DB2分页时必须要指定子查询的别名,不然会发生异常 #52
- 解决:分页取数据时,如果数据一条都没有返回, pageInfo.isIsLastPage(); 返回false #50
- 增加新的参数
countColumn
用于配置自动 count 查询时的查询列,默认值0
,也就是count(0)
Page
对象也新增了countColumn
参数,可以针对具体查询进行配置- 针对文档显示问题进行修改,by liumian* PR #30
- 解决 sqlserver2012 分页错误的问题 42
- 使用 QueryInterceptor 规范 处理分页逻辑
- 新的分页插件拦截器为
com.github.pagehelper.PageInterceptor
- 新的
PageHelper
是一个特殊的Dialect
实现类,以更友好的方式实现了以前的功能 - 新的分页插件仅有
dialect
一个参数,默认的dialect
实现类为PageHelper
PageHelper
仍然支持以前提供的参数,在最新的使用文档中已经全部更新PageHelper
的helperDialect
参数和以前的dialect
功能一样,具体可以看文档的参数说明- 增加了基于纯
RowBounds
和PageRowBounds
的分页实现,在com.github.pagehelper.dialect.rowbounds
包中,这是用于作为dialect
参数示例的实现,后面会补充更详细的文档 - 去掉了不适合出现在分页插件中的 orderby 功能,以后会提供单独的排序插件
- 去掉了
PageHelper
中不常用的方法 - 新的文档,更新历来更新日志中提到的重要内容,提供英文版本文档
- 解决 bug #149
- 将 Db2RowDialect 改为 Db2RowBoundsDialect
- 所有分页插件抛出的异常改为 PageException
- 使用新的方式进行分页,4.2版本是从5.0版本分离出来的一个特殊版本,这个版本兼容4.x的所有功能,5.0版本时为了简化分页逻辑,会去掉部分功能,所以4.2是4.x的最后一个版本。
- 支持 MyBatis 3.1.0+ 版本
- 增加对 Derby 数据库的支持
- 对除 informix 外的全部数据库进行测试,全部通过
- PageHelper增加手动清除方法
clearPage()
- 解决 SqlServer 多个
with(nolock)
时出错的问题 - 对CountMappedStatement 进行缓存,配置方式见BaseSqlUtil 319行
- 由于SqlServer的sql处理特殊,因此增加了两个SQL缓存,具体配置参考SqlServerDialect类
- 添加 sqlserver 别名进行排序功能,在解析sql时,会自动将使用的别名转换成列名 by panmingzhi
- 新增
sqlCacheClass
参数,该参数可选,可以设置sql缓存实现类,默认为SimpleCache
,当项目包含guava时,使用GuavaCache
,也可以通过参数sqlCacheClass
指定自己的实现类,有关详情看com.github.pagehelper.cache
包。 - 解决#135,增加/keep orderby/注解,SQL中包含该注释时,count查询时不会移出order by
- sqlserver没有orderby时,使用
order by rand()
#82 #118
- 通过间接处理字符串解决SqlServer中不支持
with(nolock)
的问题#86,详情可以看SqlServerParser
和SqlServer2012Dialect
- 更新
PageProviderSqlSource
,支持3.4.0版本的Provider
注解方式的分页#102 - 解决
SqlUtil
未初始化PARAMS
属性导致的错误
- 解决
closeConn
未设置时,默认值被覆盖变成false
的问题#97 closeConn
不只对动态数据源有效,当没有设置dialect
属性自动获取数据库类型的时候同样有效- 解决关闭tomcat的时候提示线程安全问题#98,这个问题不会导致内存溢出,已经增加处理
- 解决反射类没有完全捕获异常的问题#94
- 把SqlServer类所有private都改成了protected,方便继承修改#93
- 增加可配参数
closeConn
,当使用动态数据源时,分页插件获取jdbcUrl后,控制是否关闭当前连接,默认true
关闭 - count查询改为
count(0)
,分库分表情况下的效率可能更高
- 解决动态数据源时获取连接后未关闭的严重bug#80
- 解决动态数据源时SqlSource和parser绑定导致不能切换方言的问题
- 增加
autoRuntimeDialect
参数,允许在运行时根据多数据源自动识别对应方言的分页(暂时不支持自动选择sqlserver2012
,只能使用sqlserver
)。 - 去掉了4.0.3版本增加的
returnPageInfo
参数,接口返回值不支持PageInfo
类型,可以使用下面ISelect
中演示的方法获取 - 增加对
SqlServer2012
的支持,需要手动指定dialect=sqlserver2012
,否则会使用2005的方式进行分页 - jsqlparser升级到0.9.4版本,使用jar包时必须用最新的0.9.4版本,使用Maven会自动依赖0.9.4
- 增加
ISelect
接口,方便调用,使用方法可以参考src/test/java/com.github.pagehelper.test.basic.TestISelect
测试。
//jdk6,7用法,创建接口
Page<User> page = PageHelper.startPage(1, 10).setOrderBy("id desc").doSelectPage(new ISelect() {
@Override
public void doSelect() {
userMapper.selectGroupBy();
}
});
//jdk8 lambda用法
Page<User> page = PageHelper.startPage(1, 10).setOrderBy("id desc").doSelectPage(()-> userMapper.selectGroupBy());
//为了说明可以链式使用,上面是单独setOrderBy("id desc"),也可以直接如下
Page<User> page = PageHelper.startPage(1, 10, "id desc").doSelectPage(()-> userMapper.selectGroupBy());
//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(1, 10).setOrderBy("id desc").doSelectPageInfo(new ISelect() {
@Override
public void doSelect() {
userMapper.selectGroupBy();
}
});
//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).setOrderBy("id desc").doSelectPageInfo(() -> userMapper.selectGroupBy());
//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
@Override
public void doSelect() {
userMapper.selectLike(user);
}
});
//lambda
total = PageHelper.count(()->userMapper.selectLike(user));
-
PageHelper
新增3个offsetPage
方法,参数主要是offset
和limit
,允许不规则分页 -
新增两个可配参数
supportMethodsArguments
和returnPageInfo
(该参数在4.1.0版本去掉),具体含义和用法请看如何使用分页插件中的参数介绍
-
简化
Page<E>
类,包含排序条件orderBy
-
dialect
参数是数据库名称时不区分大小写 -
dialect
参数可以设置为实现com.github.pagehelper.parser.Parser
接口的实现类全限定名称 -
增加对
h2
数据库的支持 -
将
OrderByHelper
(排序插件)融合到PageHelper
中,移除OrderByHelper
-
该版本调整比较大,但对开发人员影响较小,为以后扩展和完善提供方便
-
这个改动主要是去掉了
Page<E>
构造方法中的RowBounds
,用int[]
数组替换了RowBounds
-
配置属性
dialect
不在强制要求,可以不写,分页插件会自动判断 -
解决从request中获取分页参数时的错误,感谢探路者☆
-
PageInfo
增加空构造方法,所有属性增加setter
方法 -
增加对排序的支持
-
可以单独使用
PageHelper.orderBy(String orderBy)
对查询语句增加排序,也可以配合startPage
的其他方法使用 -
可以使用
PageHelper.startPage(int start,int size,String orderBy)
对分页查询进行排序 -
修改分页查询的处理逻辑,主要是将原
sqlSource
包装成可以分页和排序的sqlSource
-
增加对MyBatis3.2.0以上版本的校验,如果是不是3.2.0以上版本,会抛出异常提示
-
解决3.7.1更新中实际没有解决的入参为不可变
Map
类型时的错误
-
为了支持
3.3.0
去掉了分页插件自带的SytemObjectMetaObject
类(该类在早期版本为了支持3.2.0以前的MyBatis) -
最新支持MyBatis - 3.2.0到最新3.3.0版本
-
Page
继承的ArrayList
,会根据pageSize
初始化大小,这就导致当pageSize
过大(如Integer.MAX_VALUE
),实际数据量很小时的内存溢出,此处改为初始化大小为0的List
。 -
当想查询某页后面的全部数据时,可以使用
PageHelper.startPage(pageNum, Integer.MAX_VALUE)
进行分页,RowBounds(offset, Integer.MAX_VALUE)
一样。 -
针对
PageHelper.startPage(1, Integer.MAX_VALUE)
优化,会取消分页,直接查询全部数据(能起到pageSizeZero
参数所起的作用)。 -
针对
RowBounds(0, Integer.MAX_VALUE)
优化,会取消分页,直接查询全部数据(能起到pageSizeZero
参数所起的作用)。
- jsqlparser解析sql会抛出Error异常,由于只捕获Exception,所以导致部分解析失败的sql无法使用嵌套方式处理,所以修改为捕获
Throwable
。
- 增加
Infomix
数据库支持,设置dialect
值为infomix
即可 - 解决入参为不可变
Map
类型时的错误
- 由于
orderby
参数经常被错误认为的使用,因此该版本全面移除了orderby
Page<E>
移除orderby
属性PageHelper
的startPage
方法中,移除包含orderby
参数的方法,sqlserver相关包含该参数的全部移除- 对SqlServer进行分页查询时,请在sql中包含order by语句,否则会抛出异常
- 当
offsetAsPageNum=false
的时候,由于PageNum问题,RowBounds
查询的时候reasonable
会强制为false,已解决 - 少数情况下的select中包含单个函数查询时,会使用嵌套的count查询
-
重构,将原来的内部类全部独立出来,尤其是
Parser
接口以及全部实现。 现在可以直接使用Parser
,使用方法如下:String originalSql = "Select * from user o where id > 10 order by id desc "; Parser parser = AbstractParser.newParser("mysql"); //获取count查询sql String countSql = parser.getCountSql(originalSql); //获取分页sql,这种方式不适合sqlserver数据库 String pageSql = parser.getPageSql(originalSql); //sqlserver用下面的方法 SqlServer sqlServer = new SqlServer(); pageSql = sqlServer.convertToPageSql(originalSql, 1, 10);
- 解决了一个潜在的bug,对通用Mapper中的
SqlMapper
进行分页时,需要使用这个版本
-
本次更新只是增加了一个异常提示,当错误的配置了多个分页插件时,会有更友好的错误提示:
分页插件配置错误:请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xml和Spring配置方式,请选择其中一种,不要同时配置多个分页插件)!
-
解决select distinct导致count查询结果不正确的bug#35
-
完善测试
-
支持db2数据库
-
支持sqlserver(2005+)数据库
-
sqlserver注意事项:
- 请先保证你的SQL可以执行
- sql中最好直接包含order by,可以自动从sql提取
- 如果没有order by,可以通过入参提供,但是需要自己保证正确(3.7.0版本以后,移除了该参数,请在sql中包含order by)
- 如果sql有order by,可以通过orderby参数覆盖sql中的order by
- order by的列名不能使用别名(
UNION,INTERSECT,MINUS,EXCEPT
等复杂sql不受限制,具体可以自己尝试) - 表和列使用别名的时候不要使用单引号(')
-
简单修改结构
-
startPage
方法返回值从void
改为Page
,获取Page
后可以修改参数值 -
Page
增加一个针对sqlserver的属性orderBy
(3.7.0版本以后,移除了该属性),用法看上面的注意事项 -
Page
增加了一个链式赋值的方法,可以像下面这样使用:PageHelper.startPage(1,10).count(false).reasonable(true).pageSizeZero(false)
-
PageHelper
增加了startPage(int pageNum, int pageSize,String orderBy)
方法(3.7.0版本以后,移除了该方法),针对sqlserver
-
解决bug#25,当参数是null并且是动态查询时,由于加入分页参数,导致参数不在是null,因而会导致部分判断出错,导致异常。
-
上面这个bug会影响使用了动态标签并且允许入参为null的所有查询,虽然并不常见,但是建议各位使用最新版本
-
增加更丰富的调用方法#23
startPage(int pageNum, int pageSize)
startPage(int pageNum, int pageSize, boolean count)
- +
startPage(int pageNum, int pageSize, boolean count, Boolean reasonable)
- +
startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero)
- +
startPage(Object params)
注:只能是Map
或ServletRequest
类型
参数中的
reasonable
、pageSizeZero
都可以覆盖默认配置,如果传null
会用默认配置。 -
为了支持
startPage(Object params)
方法,增加了一个params
参数来配置参数映射,用于从Map
或ServletRequest
中取值,详细内容看文档下面的具体介绍。 -
解决一个
<foreach>
标签使用对象内部属性循环时的bug#24
PageInfo
中的judgePageBoudary
方法修改:isLastPage = pageNum == pages && pageNum != 1; //改为 isLastPage = pageNum == pages;
-
重大bug修复,
SqlParser
解析sql失败的时候返回了不带count(*)
的sql,导致查询失败。 -
产生原因,由于
SqlParser
在系统中出现的位置修改后,导致这里出现错误。 -
强烈推荐各位更新到最新版本。
-
增加了对
@SelectProvider
注解方法的支持,不使用这种方式的不影响 -
对基本逻辑进行修改,减少反射调用和获取
BoundSql
次数
PageInfo
增加序列化。
- 动态sql时,判断条件不会出现在ParameterMappings中,会导致获取不到属性。通常是因为判断条件中的属性没有出现在
#{}
中。
-
对
MappedStatement
对象进行缓存,包括count查询的MappedStatement
以及分页查询的MappedStatement
,分页查询改为预编译查询。 -
独立的
SqlUtil
类,由于原来的PageHelper
太复杂,因此将拦截器外的其他代码独立到SqlUtil
中,方便查看代码和维护。SqlUtil
中增加Parser
接口,提供一个抽象的SimpleParser
实现,不同数据库的分页代码通过继承SimpleParser
实现。 -
特殊的
Parser
实现类SqlParser
类,这是一个独立的java类,主要提供了更高性能的count查询sql,可以根据sql自动改为count(*)
查询,自动去除不需要的order by
语句,如果需要使用该类,只要把该类放到SqlUtil
类相同的包下即可,同时需要引入Jar包jsqlparser-0.9.1.jar
。 -
增强的
PageInfo
类,PageInfo
类包含了分页几乎所有需要用到的属性值,减少了对分页逻辑的过多投入。 -
分页合理化,自动处理pageNum的异常情况。例如当pageNum<=0时,会设置pageNum=1,然后查询第一页。当pageNum>pages(总页数)时,自动将pageNum=pages,查询最后一页。
-
增加对
PostgreSQL
,MariaDB
,SQLite
支持。其中MariaDB
,SQLite
和Mysql
分页一样。
-
解决
mysql
带有for update
时分页错误的问题。 -
当
pageSize
(或RowBounds
的limit
)<=0
时不再进行分页查询,只会进行count查询(RowBounds需要配置进行count查询),相当于用分页查询来做count查询了。 -
增加了
pageSizeZero
参数,当pageSizeZero=true
时,如果pageSize=0
(或RowBounds.limit
=0),就会查询全部的结果。这个参数对于那些在特殊情况下要查询全部结果的人有用。配置该参数后会与上面第二条冲突,解决方法就是如果只想查询count,就设置pageSize<0
(如-1
),只要不等于0(或者不配置pageSizeZero)就不会出现全部查询的情况。 -
这个版本没有包含count查询时自动去除
order by
的功能,这个功能将会添加到3.3.0版本中。 -
为了便于本项目的统一管理和发布,本项目会和github上面同步,项目会改为Maven管理的结构。
-
简单重构优化代码。
-
新增
PageInfo
包装类,对分页结果Page进行封装,方便EL使用。 -
将
SystemMetaObject
类的fromObject
方法内置到分页插件中,方便低版本的Mybatis使用该插件。
-
新增
offsetAsPageNum
参数,用来控制RowBounds
中的offset
是否作为pageNum
使用,pageNum
和startPage
中的含义相同,pageNum
是页码。该参数默认为false
,使用默认值时,不需要配置该参数。 -
新增
rowBoundsWithCount
参数,用来控制使用RowBounds
时是否执行count
查询。该参数默认为false
,使用默认值时,不需要配置该参数。
-
增加了对
Hsqldb
的支持,主要目的是为了方便测试使用Hsqldb
-
增加了该项目的一个测试项目Mybatis-Sample,测试项目数据库使用
Hsqldb
-
增加MIT协议
- 解决count sql在
oracle
中的错误
- 统一返回值为
Page<E>
(可以直接按List
使用),方便在页面使用EL表达式,如${page.pageNum}
,${page.total}
-
解决了
RowBounds
分页的严重BUG,原先会在物理分页基础上进行内存分页导致严重错误,已修复 -
增加对MySql的支持,该支持由鲁家宁增加。
-
现在支持两种形式的分页,使用
PageHelper.startPage
方法或者使用RowBounds
参数 -
PageHelper.startPage
方法修改,原先的startPage(int pageNum, int pageSize)
默认求count,新增的startPage(int pageNum, int pageSize, boolean count)
设置count=false
可以不执行count查询 -
移除
endPage
方法,现在本地变量localPage
改为取出后清空本地变量。 -
修改
Page<E>
类,继承ArrayList<E>
-
关于两种形式的调用,请看示例代码
-
解决并发异常
-
分页sql改为直接拼sql
-
支持Mybatis缓存,count和分页同时支持(二者同步)
-
修改拦截器签名,拦截
Executor
-
将
Page<E>
类移到外面,方便调用
-
支持
<foreach>
等标签的分页查询 -
提供便捷的使用方式