JPA CriterialBuilder.concat force to use concat function

廉价感情. 提交于 2019-12-08 00:37:14

问题


I'm using CriteriaBuilder.concat to concatenate 2 Strings, using code below:

Expression<String> concat = criteriaBuilder.concat(expr1, expr2)

But the generated SQL is something like:

select distinct col_1 || col_2

which causes org.hibernate.hql.ast.QuerySyntaxException:

expecting CLOSE, found '||' near line 1, column 48 [
select count(distinct generatedAlias0.hostname || generatedAlias0.device) from ...
                                                ^(1,48)

I wonder how to force it to generate the following SQL which uses the concat() function, instead of the || operator?

select distinct concat(col_1, col_2)

Update:

From the error we can see that the problem is more on the Hibernate (v3.6.10.Final) side, which is why making MySQL to accept || for concatenation doesn't help, also updating to a newer version is not an option for me.

Thank you


回答1:


I've actually found a workaround. by using @Formula (from Hibernate) instead of CriteriaBuilder for the same task, like this:

@Entity
public class MyEntity {

  @Column(name="col_a")
  private String colA;

  @Column(name="col_b")
  private String colB;

  @Formula("concat(col_a, col_b)")
  private String concated;

  //...
}

This way I can use the concated field for CriteriaBuilder.countDistinct:

//...

Expression<?> exp = criteriaBuilder.countDistinct(entity.get("concated"));
criteriaQuery.select(exp);

TypedQuery<Long> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();

I wish JPA would (or hopefully already) support countDistinct with multiple columns, then all these mess could have been avoided (see: How to countDistinct on multiple columns, the answer was NO).




回答2:


I had a similar problem with the concat function. I have used the concat function in a selectCase and this also returns the same QuerySyntaxException.

My workaround is to use the concat function via criteria builder function:

cb().selectCase().when(cb().equal(root.get(Person_.flag), cb().literal("1")), 
        cb().function("CONCAT", String.class, root.get(Person_.something), cb().literal(" bla bla bla")))
    .otherwise(root.get(Person_.something))) 

Hibernate Version 4.3.11.Final



来源:https://stackoverflow.com/questions/25469858/jpa-criterialbuilder-concat-force-to-use-concat-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!