On Hibernate 6.4, one of my queries is working strangely, giving an error.
HQL - "select max(l.id.logSequenceNumber) from CmFieldOrderLog l where l.id.fieldOrderId = :order"
Everything happens in AbstractSqlAstTranslator.java:7661
This happens because SqlTupleContainer.getSqlTuple( comparisonPredicate.getRightHandExpression() ) returns null
Going down below, I see that org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation#determineResolvedExpression in my case returns jdbcParameters. get( 0 ), which contains an object of type JdbcParameterImpl, which is replaced by null in org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation#getSqlTuple, since it is not an instanceof SqlTuple.
I don’t quite understand this behavior and can’t figure out if the error is related to my custom types\parameters or queries or if something is wrong in AbstractSqlAstTranslator.java:7661. Previously (on 5.6) this query was executed correctly.
Please try to create a reproducer with our test case template and if you are able to reproduce the issue, create a bug ticket in our issue tracker and attach that reproducer.
On the migration to hibernate 6.4 we had the same error message, but a different scenario: We created a subquery in combination with predicates and tried to compare custom identity objects with each other. This lead to the error message above as well:
java.lang.NullPointerException: Cannot invoke
"org.hibernate.sql.ast.tree.expression.SqlTuple.getExpressions()" because the return value of
"org.hibernate.sql.ast.tree.expression.SqlTupleContainer.getSqlTuple(org.hibernate.sql.ast.tree.SqlAstNode)"
is null
Our workaround was to compare the long values of our custom identities directly instead of comparing the identity objects.
So I’ve scrutinized all the internal Hibernate processes that happen during my hql query and now I think it’s not a bug in 6.4, but a bug in 5.6.
The problem occurred because we were comparing embedded object CmFieldOrderExpansion_Id on the left and an object matching one of its fields of type FieldOrder_Id. The structure is as follows:
That is, the HQL looked like this: "from CmFieldOrderLog l where l.id.fieldOrderId = :order", where l.id.fieldOrderId is a field of type CmFieldOrderExpansion_Id , and :order is fieldOrderId.
In 5.6 it worked, although it should not - comparison of objects of different types.
6.4 now it doesn’t work, because Embeddable is always treated as tuple, and accordingly the object in the right part is not. because of this we get a situation where this hibernate code will execute
if ( lhsTuple.getExpressions().size() == 1 ) {
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
if ( subquery == null ) {
renderComparison(
lhsTuple.getExpressions().get( 0 ),
operator,
SqlTupleContainer.getSqlTuple( comparisonPredicate.getRightHandExpression() ).getExpressions().get( 0 ))
);
}
And there will be an NPE.
I don’t think it’s a hibernate error - the HQL was incorrect after all, but I would advise to handle such cases somehow so that the error is more clear.
Yeah, we should definitely improve the error message. Can you please share the reproducer so we can work with that when trying to improve error reporting?