When using the CriteriaQuery API and invoking a query using the uniqueResultOptional() methodthrows a QueryException for a Named parameter not set. This exception is not thrown if the JPA method getResultList() is used instead.
After debugging this I determined the root cause is the Query returned by Session.createQuery(CriteriaQuery) is a CriteriaQueryTypeQueryAdapter. It overrides the methods for getSingleResult() and getResultList() to invoke the corresponding methods on its jpqlQuery method, a fully populated QueryImpl. Hibernate-specific methods, including uniqueResultOptional() are not overridden by CriteriaQueryTypeQueryAdapter, and thus the corresponding methods are not invoked on the jpqlQuery member.
Here is a sample source that causes the problem:
And a stack trace snippet illustrating the issue:
As one would expect, the same problem arises with scroll(), and presumably the corresponding method from org.hibernate.query.Query#stream(), which uses scroll() under the covers.
If Session#createQuery(CriteriaQuery) does not return a org.hibernate.query.Query then it cannot be used as a replacement for the Criteria API, which provides a method for scrolling through results using a cursor. This will force Hibernate 4.x based applications to migrate to the HQL interface instead.
My bad - I can use javax.persistence.Query#unwrap( org.hibernate.query.Query ) to get the underlying query and use all Hibernate APIs. This seems clearer since only TypedQuery methods are @Override by CriteriaQueryTypeQueryAdapter, so I agree that Session#createQuery(CriteriaQuery) should return a javax.persistence.TypedQuery.
org.hibernate.query.Query is a javax.persistence.TypedQuery