首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

Hibernate运用ANTLR语法解析器对HQL的解析BUG

2012-07-16 
Hibernate使用ANTLR语法解析器对HQL的解析BUG[u][/u]公司产品中有一处判断生日月份的HQL语句,以前用得好好

Hibernate使用ANTLR语法解析器对HQL的解析BUG
[u][/u]公司产品中有一处判断生日月份的HQL语句,以前用得好好的,突然到了8月份的时候,这条语句出错了。HQL语句大概是from User u where month(u.birth) = 08 。后来猜测想到可能08有前置0,被当成了8进制处理了。把08改为8后,果然问题解决了。这证明猜想是正确的,但以前一直没研究过Hibernate的实现,于是想在网上搜索关于这个问题的答案,结果搜索不到,又想知道其实现的机制,于是下载代码下来看了一翻,发现问题出在Hiberante自定义的语法处理规则问题上,并且还找到了其中的一个BUG。



分析一下Hibernate对HQL中对前置0的数字的处理规则:

Hibernate对HQL生成SQL的校验是使用antlr语法分析器来做正确性保证的,其有自定义语法文件hql.g里对数字处理规则为如有前置0则进一步分析2种情况:
1、如果接下来有“x” 则表示为16进制,采用16进制分析。分析OK, 然后进入语义解析,依然会出现数字转换的错误,这里的错误后面我会讲。

2、如果没有“x”,则表示是8进制,根据语法文件定义0后面只接受0-7的数字,如果超出则会语法检查失败。抛出异常,程序结束。


总结:Hibernate在对HQL进行转换SQL时,调用antlr开源语法分析器进行语法的分析检查,解析正确后Hibernate的语义分析器LiteralProcessor在 转换整数时的代码有一个BUG,转码整数时只处理10进制,所以在16进制的情况下,会出现错误,因为有0x 这个x非数字符号在内导致 Integer.parseInt的失败。 如果不出现错误的话,也可能会因为其他进制被转换成10进制出现的与真实数字的偏差,比如:一个8进制数字 011,真正转换为10进制应该是9才对,但Integer.parseInt会将其转换10进制数11,这样就会导致出错的出现了.因此你想写8进制的011实际上在Hb里就会被转换为10进制的11。

出现这种问题所在就是: 语法分析器对整型数值的处理规则与实际Hibernate的语义分析器对数值转型的不一致导致的差别。

建议:在进行程序SQL编写中的条件的数字有前置0的时候那么要注意,这个值可能在计算机里会被分析器解析成8进制数字,但又可能直接被当作10进制处理。
所以最好所有数字都以10进制的形式传入保证程序的正确性。不要写前置0。

我认为此处的代码应该调用 Integer.decode方法才是正确的,另外对长整形的处理也是类似的。

以前我几乎不在网上写技术方面的内容,这些天来有感于自己当时到对一些问题搜索不到解决方案,所以才将此记录上来,供大家遇到此类问题的参考。

热点排行