最近在改一份二手代码的时候,项目运行报了个java.lang.IllegalArgumentException: node to traverse cannot be null异常。
WTF?!难道我HQL写错了?!我只是添加了一个update方法而已啊!
这里使用的是JPA的Query注解,其实语法跟HQL是一样的,我已经把这行HQL每个空格都TM检查过了,没有发现任何奇怪的东西,没办法了只好调试一下源码
最先抛出异常的是在Hibernate的orghibernatehqlinternalastutilNodeTraverser.java:46,这里判断如果AST为空,则抛出异常,那AST到底是个啥啊?
通过跟踪NodeTraverser的调用,可看到ACT是从parser获取的,而这里的parser实际上就是Hibernate的Hql语法分析器!因此网上很多文章都会得出本文提到的异常就是HQL语法错误导致的了。但是我这个HQL明显没有语法错误的,问题又出在哪呢?我们加个短点瞧一瞧:
好玩的事情来了,如果HQL是select开头的话,是不会报错的
等到一条update了,果然parser处理后的hqlAst是空的对比上面Select语句就可以明显看出问题所在了:问题出在了parser.statement()里,那跟进去看看囖:
逐行调试,发现在执行updateStatement()时抛出异常,再跟进去:
跑到default去了
因为LA(1)是41,不在switch的任何分支里,然后实际上我在这花了很多时间,都浪费在看antrl的源码上了,就是想搞明白LA是在那里设值的,结果越看越懵逼,但实际上我们可以换个思路,通过监控每一步执行后的各个变量可以发现有这样的规律:
上图是在执行match(UPDATE)前,各个主要变量如图所示
直到执行了match方法后,LA(1)变为了41,而同时,LT(1)里的值引起了我的注意:
上面已经提到过了,实际上这部分代码是Hibernate的HQL语法解析器,那讲道理的话,第一次执行,处理完UPDATE关键字,往后应该是第二个关键字,而实际上我们的HQL中根被没有order这个词啊,为什么会导致报错呢?
还记得上面的某个断点么,就是调用parser.statement()的地方,来看看交由parser处理时的hql是什么样子的
你们发现问题了吗?Hibernate在处理hql的时候,是会把包名补全的,而这个实体类的包名是以order开头的!update关键字后不能有order关键字...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/76583.html
摘要:第二步自终止,第三步自调用,第四步回调函数会重复进行,直到我们遍历到树的所有节点。执行回调函数,传入赋值为第二层第二个子节点。 本文译自Cho S. Kim的文章:Data Structures With JavaScript: Tree 树,是web开发中最常用的数据结构之一。这句话对开发者和用户来讲,都适用:开发人员通过HTML创造了一个DOM,用户则通过DOM消费网络信息。 ...
阅读 3845·2021-07-28 18:10
阅读 2554·2019-08-30 15:44
阅读 1061·2019-08-30 14:07
阅读 3416·2019-08-29 17:20
阅读 1558·2019-08-26 18:35
阅读 3514·2019-08-26 13:42
阅读 1793·2019-08-26 11:58
阅读 1544·2019-08-23 18:33