之前检查生产日志的时候发现过一个奇怪的现象,数据库报错,sql语句错了,有两个limit
这种错误不应该出现在生产日志上,有点惊讶,我都怀疑是不是有成员的代码没有经过测试就发布了
但是当我把sql拿下来查找的时候,却发现报错的代码段,sql是正常的,仅有一个limit,拿去数据库跑
结果也是符合预期的
这让我想到了pagehelper,这个插件的功能是帮助你分页,它会帮你加入limit
我回到业务层去找相应的代码,也没找到分页助手相关的代码,但我还是怀疑是它有问题。
我翻看它的源码,发现了下面的对象,这个线程常量是它所持有的。
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();
还有多个线程变量被持有了,用来记录分页相关的信息。
pagehelper会在使用完后将它清除
public static void clearPage() { LOCAL_PAGE.remove(); }
@Override public void afterAll() { //这个方法即使不分页也会被执行,所以要判断 null AbstractHelperDialect delegate = (); if (delegate != null) { (); (); } clearPage(); }
afterAll方法是在分页的代码里加在了拦截方法的finally代码块,如果分页报错了,仍然要把线程变量清除掉。
} finally { (); }
但是问题也在这里,如果你使用PageHelper的时候,不是和dao层方法连在一起的,中间还有逻辑,那么中间
逻辑报错了,或者逻辑判断导致dao层代码不执行,这个PageHelper的分页信息,就留在了线程里,tomcat线程池
的线程复用的时候,就会把原本正常的请求也被PageHelper加了分页操作,报错的话还能及时察觉,不然你的整个
业务逻辑都产生了问题,根本不是分页的,自动分页处理会导致数据漏处理。
解决方法:使用PageHelper的时候把dao层代码写在一起,不要拆分,即使你当前确保中间没有问题,后来的人
也可能继续加入内容而导致问题,把坑留到了后面。