Details
-
Type:
Bug
-
Status: Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects versions: 5.2.10
-
Fix versions: 6.0.0.Beta1
-
Components: hibernate-core
-
Labels:None
-
Bug Testcase Reminder (view):
-
Last commented by a user?:true
-
Sprint:
Description
I have the following code snippet:
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<String> q = cb.createQuery(String.class); Root<JPABook> from = q.from(JPABook.class); q.select(cb.<String>selectCase() .when(cb.equal(from.get("title"), cb.literal("Animal Farm")), cb.literal("Animal Farm")) .otherwise(cb.nullLiteral(String.class))); em.createQuery(q).getResultList();
It generates this SQL string:
select case when jpabook0_.title=? then 'Animal Farm' else cast(null as varchar(255)) end as col_0_0_ from t_book jpabook0_
As you can see, the literal in the CASE expression's predicate is sent to the server as a bind variable, whereas the literal in the THEN clause is sent as a literal.
I personally believe that the latter is correct because the intention of using CriteriaBuilder.literal() is for an actual literal to make it into the generated SQL string. Because if users wanted a parameter, they could have used CriteriaBuilder.parameter() instead. What's the point of literal() if it still generates a parameter.
I've already had this discussion with Vlad Mihalcea on Twitter:
https://twitter.com/lukaseder/status/869209243282530304
Even if you might not agree with the above, I think the behaviour of all CriteriaBuilder.literal() calls should be consistent, so:
- Either generate only actual literals in generated SQL (properly escaping them of course!)
- Or generate only bind variables in generated SQL
Side-note: try using a Java string containing an apostrophe instead in both places: "This isn't working" and see what happens...
Related issue: https://hibernate.atlassian.net/browse/HHH-9576