ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浅析PageHelper踩坑:不安全分页导致的问题

2021-08-29 23:01:51  阅读:271  来源: 互联网

标签:分页 list PageHelper ThreadLocal 参数 线程 浅析


  这个问题的起因是后端日志经常有一个报错:Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: syntax error at or near "LIMIT"。

  但是奇怪的是那个查询方法根本就没有 limit,其次不清楚原因。后来才清楚为什么,因为我们使用了 分页插件 PageHelper,在使用 PageHelper 的时候如果不注意,就会导致不安全的分页问题。

一、结论先行

  主要原因:PageHelper 使用了静态的 ThreadLocal 参数,让线程绑定了分页参数, 这个参数如果没被使用就会一直留在那儿,当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。

二、造成原因:

  什么时候会导致不安全的分页? PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

  只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

  如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

  但是如果你写出下面这样的代码,就是不安全的用法:

PageHelper.setPage(1,10);
if(param!=null){
    list=userMapper.selectIf(param)
}eles{
    list=new ArrayList<User>();
}

  这样子如果 param 没有消费到,那么接下来如果进去了其他方法使用了 select 方法就会将这个page参数带进去,被消费;

  如何改进呢?

if(param!=null){
    PageHelper.setPage(1,10);
    list=userMapper.selectIf(param)
}eles{
    list=new ArrayList<User>();
}

  避坑:让这个分页参数紧跟查询,可以查就建立;也就是保证被消费;或者在 finally 调用 PageHelper.clearPage(); 清除。

  这种写法就能保证安全。如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:

List<Country> list;
if(param1 != null){
    PageHelper.startPage(1, 10);
    try{
        list = countryMapper.selectAll();
    } finally {
        PageHelper.clearPage();
    }
} else {
    list = new ArrayList<Country>();
}
// 这么写很不好看,而且没有必要

三、其他问题介绍

  最近在项目中频繁出现 sqlException,报错有两种情况,一种是拼接了order by ‘column’,一种是拼接了limit ‘num’;奇怪的是我的sql语句中并没有这些参数。

1、error1:在这里出现了未识别的字段

2、error2:sql语句中已经写了limit,pagehelper又拼接了一次,出现 'limit 1 limit 10’的情况;

  通过百度,了解到PageHelper使用了静态的ThreadLocal参数,分页参数和线程是绑定的;当分页参数没有被消费时,会一直存在threadlocal中,在下一次执行的sql中会拼接这些参数。

  那么怎么避免这种情况:分页参数紧跟 list 查询。如果先写分页,又写了别的判断逻辑,没有执行 list 查询时,那么分页参数就会在threadlocal中,下次执行sql会消费这些参数,就会导致“不安全分页”。

标签:分页,list,PageHelper,ThreadLocal,参数,线程,浅析
来源: https://www.cnblogs.com/goloving/p/15203934.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有