问题
使用PageHelperi分页,报错如下:
Caused by: com.alibaba.druid.sql.parser.ParserException: syntax error, error in :’limi1 1 limit ?,?’,expect LIMIT, actual LIMIT limit
原始查询sql(select * from t limit 1)后面有limit1,结果报错显示自动添加上上limit ?,?:
排查
见PageHelper 安全调用:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/blob/master/wikis/zh/HowToUse.md#3-pagehelper-安全调用
PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
线程中start的page 不能保证线程在当前执行退出时清理完page变量
重现
XXXServiceImpl {
XX method(Object xx, int pageNum, int pageSize) {
PageHelper.start(pageNum,pageSize);
if(xx!=null){
return XX;
}
xxxMapper.find();
....
}
}
在执行PageHelper.start(pageNum,pageSize);方法后,参数page变量,如xx!=null,直接返回XX,则page没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,如果接下来执行其它sql,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
如果PageHelper.start(pageNum,pageSize);之后的方法加了缓存,也会有这个问题。
解决方法
1.使用参数方式是极其安全的2.保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,必须保证分页和查询同时有效。3.调PageHelper.clearPage(); 可以手动清理 ThreadLocal 存储的分页参,这个是新版本里的方法 其中5.0之后版本注意:
1. 配置文件中PageHelper变为了PageInterceptor
<plugin interceptor=”com.github.pagehelper.PageInterceptor”>
2. 不需要<property name=”dialect” value=”mysql”/>,自动识别数据库