[英]How to group by Case statement using JPA Criteria API / Hibernate
I am trying to perform a query like the following, with selecting by a case statement and grouping by the same case statement.. 我正在尝试执行如下所示的查询,通过case语句进行选择并按相同的case语句进行分组。
Select USER,
(CASE
WHEN value between 0 AND 2 then '0-2'
WHEN value between 3 AND 4 then '3-4'
ELSE '5+'
END) as CASE_STATEMENT ,
SUM(value)
.....
Group by user, CASE_STATEMENT
using JPA 2.0 Criteria API, with Hibernate. 使用JPA 2.0 Criteria API和Hibernate。
My test case looks like ... 我的测试用例看起来像......
CriteriaBuilder cb = em.getCriteriaBuilder()
CriteriaQuery cq = cb.createQuery(Tuple)
def root = cq.from(TestEntity)
def userGet = root.get('user')
def valueGet = root.get('value')
def caseExpr =
cb.selectCase()
.when(cb.between(valueGet, 0, 2), '0-2')
.when(cb.between(valueGet, 3, 4), '3-4')
.otherwise('5+')
def sumExpr = cb.sum(valueGet)
cq.multiselect([userGet, caseExpr, sumExpr])
cq.groupBy([userGet, caseExpr])
log(typedQuery.unwrap(Query).queryString)
List<Tuple> tuples = typedQuery.getResultList()
The log statement of the queryString reads queryString的日志语句读取
SELECT generatedAlias0.USER,
CASE
WHEN generatedAlias0.value BETWEEN 0 AND 2 THEN Cast(:param0 AS STRING)
WHEN generatedAlias0.value BETWEEN 3 AND 4 THEN Cast(:param1 AS STRING)
ELSE Cast(:param2 AS STRING)
END,
Sum(generatedAlias0.value)
FROM test AS generatedAlias0
GROUP BY generatedAlias0.USER,
CASE
WHEN generatedAlias0.value BETWEEN 0 AND 2 THEN Cast(
:param3 AS STRING)
WHEN generatedAlias0.value BETWEEN 3 AND 4 THEN Cast(
:param4 AS STRING)
ELSE Cast(:param5 AS STRING)
END
When calling the typedQuery.getResultList(), I get the following error statement 调用typedQuery.getResultList()时,我得到以下错误语句
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not extract ResultSet
Caused by: org.h2.jdbc.JdbcSQLException: Column "TESTENTITY0_.VALUE" must be in the GROUP BY list; SQL statement:
select testentity0_.user as col_0_0_, case when testentity0_.value between 0 and 2 then cast(? as varchar(255)) when testentity0_.value between 3 and 4 then cast(? as varchar(255)) else cast(? as varchar(255)) end as col_1_0_, sum(testentity0_.value) as col_2_0_ from test testentity0_ group by testentity0_.user , case when testentity0_.value between 0 and 2 then cast(? as varchar(255)) when testentity0_.value between 3 and 4 then cast(? as varchar(255)) else cast(? as varchar(255)) end [90016-194]
Is there something wrong with the way I am trying to group by the Expression? 我试图通过表达式分组的方式有什么问题吗? I have also tried grouping by alias names, and by number literals (1, 2) 我也尝试按别名和数字文字分组(1,2)
Is there another way I can go about structuring the SQL to get the same results? 有没有其他方法可以构建SQL以获得相同的结果?
Thanks. 谢谢。
As the exception message suggests, the problem is related to the Group By
statement at DBMS level. 正如异常消息所示,该问题与DBMS级别的Group By
语句有关。 See: https://www.percona.com/blog/2019/05/13/solve-query-failures-regarding-only_full_group_by-sql-mode/ 请参阅: https : //www.percona.com/blog/2019/05/13/solve-query-failures-regarding-only_full_group_by-sql-mode/
To solve the error, you must either 要解决错误,您必须要么
Set the Group By Mode
of the underlying DBMS to a less restrictive level (MySQL allows to disable only-full-group-by , but H2 does not (you may try setting MODE=MYSQL
in jdbc connection string) 将基础DBMS的Group By Mode
设置为较低限制级别(MySQL允许仅禁用全分组 ,但H2不允许 (您可以尝试在jdbc连接字符串中设置MODE=MYSQL
)
or (better) 或 (更好)
Add all columns that are part of the select statement to the GROUP BY
statement or to an aggregate function as described above . 将属于select语句的所有列添加到GROUP BY
语句或添加到聚合函数, 如上所述 。
You should be able to build a nested query which fulfills the GROUP BY RESTRICTIONS. 您应该能够构建一个满足GROUP BY RESTRICTIONS的嵌套查询。
For the rescue, there are some (maybe DBMS specific) aggregate functions (at least in MySQL ). 为了救援,有一些(可能是DBMS特定的)聚合函数(至少在MySQL中 )。 To trick JPA and Hibernate to understand these, there are several ways to achieve this, as described at https://vladmihalcea.com/hibernate-sql-function-jpql-criteria-api-query/ and https://vladmihalcea.com/the-jpa-entitymanager-createnativequery-is-a-magic-wand/ 为了让JPA和Hibernate理解这些,有几种方法可以实现这一点,如https://vladmihalcea.com/hibernate-sql-function-jpql-criteria-api-query/和https://vladmihalcea.com所述。 /所述-JPA-的EntityManager-createnativequery-是-A-魔棒/
Edit 编辑
In contrast and addition to the statement above, the findings after discussion below are: 与上述陈述相反,经过以下讨论后的调查结果如下:
org.h2.expression.ExpressionColumn
class, while it's verifying the query syntax org.h2.expression.ExpressionColumn
类中的h2驱动程序引发异常,同时验证查询语法 List<Tuple> tuples = em.createNativeQuery(
"SELECT generatedAlias0.USER, " +
" CASE " +
" WHEN generatedAlias0.value BETWEEN 0 AND 2 THEN Cast(:param0 AS VARCHAR) " +
" WHEN generatedAlias0.value BETWEEN 3 AND 4 THEN Cast(:param1 AS VARCHAR) " +
" ELSE Cast(:param2 AS VARCHAR) " +
" END c, " +
" Sum(generatedAlias0.value) as sumvalue " +
"FROM test AS generatedAlias0 " +
"GROUP BY generatedAlias0.USER, c "
)
.setParameter("param0", "0-2")
.setParameter("param1", "3-4")
.setParameter("param2", "5+")
.getResultList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.