具有COALESCE的条件API计数记录引发QuerySyntaxException

时间:2019-07-11 10:34:27

标签: hibernate jpa criteria criteria-api

是否可以合并记录计数?在Oracle中,可以使用以下选择:

    SELECT
    COUNT(DISTINCT coalesce(foo.parent, foo.ident)) AS c    FROM
    FOO foo;

我尝试使用此代码:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
Root root = criteriaQuery.from(Foo.class);
CriteriaBuilder.Coalesce<Long> coalesce = criteriaBuilder.coalesce();
coalesce.value(root.<Long> get("parent"));
coalesce.value(root.<Long> get("id"));
CriteriaQuery<Long> select = criteriaQuery.select(criteriaBuilder.countDistinct(coalesce));
TypedQuery<Long> typedQuery = entityManager.createQuery(select);
return typedQuery.getSingleResult();

但这会引发异常

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting CLOSE, found '(' near line 1, column 31

生成的查询

[select count(distinct coalesce(generatedAlias0.parent, generatedAlias0.id)) from foo.Foo as generatedAlias0]

1 个答案:

答案 0 :(得分:1)

作为针对问题注释的错误HHH-9182(由@Tijkijiki指向)的解决方法,您可以使用CASE表达式代替COALESCE

所以您的标准应该是:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
Root root = criteriaQuery.from(Foo.class);
Expression<Long> selectCase = builder<Long>selectCase()
    .when(builder.isNotNull(root.get("parent")), root.get("parent"))
    .otherwise(root.get("id"));
CriteriaQuery<Long> select = 
criteriaQuery.select(criteriaBuilder.countDistinct(selectCase));
TypedQuery<Long> typedQuery = entityManager.createQuery(select);
return typedQuery.getSingleResult();