error querying(Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column xxx in where clause)
在使用Ruoyi管理系统中出现这个问题
Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column xxx_time in where clause因为对应报错的SQL中没有该字段 ,前端也没有传入该字段 ,而且这个问题是偶发的,所以一直也没查到原因 。
今天心血来潮追溯了下源码隐约发现了问题所在 。 # 首先声明: # 1.先确认是不是确实是字段写错了 # 2.这个锅Ruoyi不背 ,PageHelper也不背 ,问题肯定就是出在业务代码里 。 # 解决方式: # 1.确保PageHelper的startPage方法之后直接执行doSelect ,不存在doSelect之前中途返回或者还有其他查询的情况 # 2.现有代码中误用太多不方便全改 ,可以在拦截器返回的时候调用下clearPage清除下缓存先说下我们的代码场景
1.controller层的list接口调用了Ruoyi封装类PageUtils.startPage()无参方法
2.startPage方法之后调用了service层的业务方法
3.service层的业务方法中对请求参数做了一系列判断 ,异常则返回 ,最后执行mybatis里的查询下面简单分析下原因
先来看下使用的PageUtils.startPage() /** * 设置请求分页数据 */ public static void startPage() { PageDomain pageDomain = TableSupport.buildPageRequest(); Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize(); String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); Boolean reasonable = pageDomain.getReasonable(); PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); }这个orderBy有点像我在找的东西 ,追溯一下PageHelper.startPage(pageNum, pageSize, orderBy) ,里面有这么两个方法
/** * 开始分页 * * @param pageNum 页码 * @param pageSize 每页显示数量 * @param orderBy 排序 */ public static <E> Page<E> startPage(int pageNum, int pageSize, String orderBy) { Page<E> page = startPage(pageNum, pageSize); // 这里可疑 page.setOrderBy(orderBy); return page; } /** * 开始分页 * * @param pageNum 页码 * @param pageSize 每页显示数量 * @param count 是否进行count查询 * @param reasonable 分页合理化,null时用默认配置 * @param pageSizeZero true且pageSize=0时返回全部结果 ,false时分页,null时用默认配置 */ public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) { Page<E> page = new Page<E>(pageNum, pageSize, count); page.setReasonable(reasonable); page.setPageSizeZero(pageSizeZero); // 当已经执行过orderBy的时候 // 这一段也可疑 Page<E> oldPage = getLocalPage(); if (oldPage != null && oldPage.isOrderByOnly()) { page.setOrderBy(oldPage.getOrderBy()); } setLocalPage(page); return page; }看代码里找到了这个比较可疑的getLocalPage()方法,然后发现是个ThreadLocal ,感觉这里应该是有问题 ,但是一时半会儿又不知道确切的问题点 。
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>(); /** * 获取 Page 参数 * * @return */ public static <T> Page<T> getLocalPage() { return LOCAL_PAGE.get(); }查了下PageHelper线程的问题,发现了这篇文章 又遇PageHelper线程污染 ,知道了“线程污染 ”这个词儿 ,感觉用的很贴切啊 。还有这篇文章里链接的另一篇文章也很值得看下 不规范使用PageHelper导致线程污染 。
为什么之前在其他springboot项目里没有出现过这个问题,使用了Ruoyi框架之后会出现呢 ,这和Ruoyi的demo也有点关系 ,demo是在controller层使用的PageHelper的startPage()无参方法 ,然后调用service层的查询方法 。
这个只适合直接查询数据库的方式使用 ,而我们直接拿来就用 ,无脑的往里面添加业务逻辑 。功能复杂一点的时候service层的业务代码出现了异常情况可能直接就返回了 ,没有走到SQL查询 。以上有部分可能不严谨 ,我分别调试了几种情况。
但是诡异的是 ,同一套代码反复跑了几遍 ,结果竟然不一样 。 。。
突然就感觉 物理学不存在了 遇到薛定谔了 。 。。
我在拦截器里添加了日志 、调用了下PageHelper.clearPage()方法,后续再观察一下吧 。创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!