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 参数被错误的使用。

但像上面那样生产了分页参数却没有消费,就会导致分页不安全,从而产生错误。

posted @ 2021-01-12 22:24  Sky-Climber  阅读(330)  评论(0)    收藏  举报