这两天遇到一个bug,写的testcase在本地没错,到CI上就报错。查了一下log,发现原因是本地跑testcase时hijack了配置文件,注释掉了以下这句
login.setShouldBindAllParameters(true);
这样让Toplink不使用参数绑定,比较方便查看输出的SQL,而CI上使用了参数绑定,所以出问题了
不使用参数绑定时,输出是这样的SQL,没有问题
SELECT trunc(t.create_time, 'DD') ta, COUNT(0) cnt FROM ts_task t GROUP BY trunc(t.create_time, 'DD')
使用参数绑定时,'DD'被绑定了,,相当于以下SQL
SELECT trunc(t.create_time, :1 ) ta, COUNT(0) cnt FROM ts_task t GROUP BY trunc(t.create_time, :2 )
这样即使:1和:2 都绑定相同的'DD',但Oracle并不会发现这个信息,从而报了
ORA-00979: not a GROUP BY expression
其实,如果Toplink能够比较绑定参数,把相同的参数归为一个占位符,从而生成以下SQL,那么还是可以用绑定还是可以的
SELECT trunc(t.create_time, :1 ) ta, COUNT(0) cnt FROM ts_task t GROUP BY trunc(t.create_time, :1 )
遗憾的是,至少在Toplink 10.1.3中还没有实现此功能。
最后的解决方法嘛,在ReportQuery一级使用了setShouldBindAllParameters(false)方法。这付出了执行计划不能重用的代价(因为Oracle是将整个SQL statement和SGA中缓存的执行计划作文本匹配的,这样换了后每换一个条件都要重新分析,缓存基本没用了),不过我也没想到更好的办法了