HSQLDB和group by的奇怪行为

时间:2012-12-25 10:07:41

标签: junit aggregate-functions hsqldb dbunit

我使用HSQLDB编写junits,我的查询是这样的:

String queryStr = "from ManualUrlBatchModel where status IN(:status) group by batchUser order by creationTime";
        Query query = getSession(requestType).createQuery(queryStr);
        query.setParameterList("status", status);

我在给定状态下检索每个用户一个批次(取决于创建时间FIFO顺序)。

它适用于端到端测试,但在编写junits时失败。

例外说:

Caused by: java.sql.SQLException: Not in aggregate function or group by clause: org.hsqldb.Expression@164f8d4 in statement [select manualurlb0_.manual_url_batch_id as manual1_7_, manualurlb0_.creation_time as creation2_7_, manualurlb0_.modification_time as modifica3_7_, manualurlb0_.attribute_list as attribute4_7_, manualurlb0_.batch_name as batch5_7_, manualurlb0_.batch_user as batch6_7_, manualurlb0_.input_s3_key as input7_7_, manualurlb0_.locale as locale7_, manualurlb0_.notify_when_complete as notify9_7_, manualurlb0_.output_s3_key as output10_7_, manualurlb0_.processed_url_count as processed11_7_, manualurlb0_.s3_bucket as s12_7_, manualurlb0_.status as status7_, manualurlb0_.submitted_url_count as submitted14_7_, manualurlb0_.total_url_count as total15_7_ from csi_manual_url_batch manualurlb0_ where manualurlb0_.status in (? , ?) group by manualurlb0_.batch_user order by manualurlb0_.creation_time]
    [junit]     at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    [junit]     at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
    [junit]     at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
    [junit]     at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
    [junit]     at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:452)
    [junit]     at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
    [junit]     at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1573)
    [junit]     at org.hibernate.loader.Loader.doQuery(Loader.java:696)
    [junit]     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
    [junit]     at org.hibernate.loader.Loader.doList(Loader.java:2228)

我在网上发现了几件事:

  1. 如果group by不是基于字符串,则GROUP BY在HSQLDB中不起作用。
  2. GROUP BY不能按我使用的方式工作(按COL1选择* ....组)。
  3. 我相信人们早些时候会遇到这个问题,那时你们做了什么(除了不写junits :))? 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:6)

在标准SQL中,group by子句必须包含除聚合函数之外的所有选定值。

select a, b, c, d, sum(e) from table group by a -- INVALID
select a, b, c, d, sum(e) from table group by a, b  -- INVALID
select a, b, c, d, sum(e) from table group by a, b, c  -- INVALID
select a, b, c, d, sum(e) from table group by a, b, c, d -- VALID

Hibernate生成的查询因此无效,而AFAIK是通过HQL查询工作创建组的唯一可能方法是列出要明确选择的每个标量列(请参阅https://hibernate.onjira.com/browse/HHH-1615):

 select m.foo, m.bar, m.creationTime, m.batchUser  
 from ManualUrlBatchModel m 
 where m.status IN(:status) 
 group by m.foo, m.bar, m.creationTime, m.batchUser 
 order by m.creationTime

如果您的原始查询适用于MySQL,那是因为MySQL不遵守SQL标准,并允许group by的查询未列出每个选定的列。我建议不要依赖这个“功能”,在测试和生产中使用相同的数据库,并使用PostgreSQL而不是MySQL。

答案 1 :(得分:0)

您也可以汇总您不想分组的所有选择值:

例如select a, sum(b), sum(c), sum(d), sum(e) from table group by a; -- VALID