I have the following code snippet:
It generates this SQL string:
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:
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