Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA CriterialBuilder.concat force to use concat function

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

like image 315
ryenus Avatar asked Sep 03 '25 03:09

ryenus


2 Answers

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).

like image 84
ryenus Avatar answered Sep 05 '25 00:09

ryenus


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

like image 43
J3ernhard Avatar answered Sep 04 '25 23:09

J3ernhard