PageHelper异常增加limit
问题
先调用使用了PageHelper分页的接口,再调用不用分页的接口,就会报错
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select id, application_code, application_name,application_token, create_time, update_time from t_app_info where application_code = ? LIMIT 1 LIMIT ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 15' at line 7
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 15' at line 7
会莫名加上 LIMIT 15,导致报错。LIMIT 15 是第一个分页接口的参数,怀疑是第一个接口影响了第二个接口。
解决
经查看PageHelper相关文档,怀疑是不安全使用引起的。
分页接口代码
@GetMapping
public RespEntity getUserList(PageModule pageModule, String search) {
Page page = PageConfig.pageConfig(pageModule);
List<UserBaseInfo> userBaseInfoList = new ArrayList<>();
if (StringUtil.isNotEmpty(search)) {
userBaseInfoList = userService.queryUserList(search);
}
return new RespEntity(RespCode.SUCCESS, PageConfig.pageDataAssemble(pageModule, page, userBaseInfoList));
}
当search为空的时候,会导致PageHelper生产了一个分页参数,但没有被消费掉,那么这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就会消费这个分页参数,产生不必要的分页。
修改代码如下:
@GetMapping
public RespEntity getUserList(PageModule pageModule, String search) {
if (StringUtil.isNotEmpty(search)) {
Page page = PageConfig.pageConfig(pageModule);
List<UserBaseInfo> userBaseInfoList = userService.queryUserList(search);
return new RespEntity(RespCode.SUCCESS, PageConfig.pageDataAssemble(pageModule, page, userBaseInfoList));
}else{
return new RespEntity(RespCode.SUCCESS, new ArrayList<>());
}
}
或者手动清除分页ThreadLocal存储的分页参数
@GetMapping
public RespEntity getUserList(PageModule pageModule, String search) {
Page page = PageConfig.pageConfig(pageModule);
List<UserBaseInfo> userBaseInfoList = new ArrayList<>();
if (StringUtil.isNotEmpty(search)) {
userBaseInfoList = userService.queryUserList(search);
}
PageHelper.clearPage();
return new RespEntity(RespCode.SUCCESS, PageConfig.pageDataAssemble(pageModule, page, userBaseInfoList));
}
相关技术点
PageHelper 方法使用了静态的 ThreadLocal,分页参数和线程是绑定的。
只要保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
如果代码在进入 Executor 前发生异常,就会导致线程不可用,(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时),这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。
但像上面那样生产了分页参数却没有消费,就会导致分页不安全,从而产生错误。

浙公网安备 33010602011771号