I just upgraded Hibernate ORM from 6.2.9 to 6.3.1 and I am getting this pretty weird validation error:
Caused by: org.hibernate.query.SemanticException: Multi valued paths are only allowed for the member of operator
at org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable(TypecheckUtil.java:329) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
at org.hibernate.query.sqm.tree.predicate.SqmInListPredicate.implyListElementType(SqmInListPredicate.java:139) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
Caused by: org.hibernate.query.SemanticException: Multi valued paths are only allowed for the member of operator
at org.hibernate.query.sqm.tree.predicate.SqmInListPredicate.<init>(SqmInListPredicate.java:61) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:2612) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:268) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
at org.hibernate.grammars.hql.HqlParser$InPredicateContext.accept(HqlParser.java:6046) ~[hibernate-core-6.3.1.Final.jar:6.3.1.Final]
I have this query:
@Query(
"""
select distinct sp
from CloudSubscriptionPlan sp
left join CloudSubscription s on s.activePlan = sp
where sp.id = :id
and (sp.public = true or :organizationId in (sp.forOrganizationIds) or s.organizationId = :organizationId)
"""
)
fun findForOrganization(id: Long, organizationId: Long): CloudSubscriptionPlan?
And the CloudSubscriptionPlan entity looks like this:
Assuming that forOrganizationIds is a plural attribute i.e. collection, your predicate should rather be :organizationId member of sp.forOrganizationIds instead of :organizationId in (sp.forOrganizationIds). Pervious versions of Hibernate probably added a join to the main query for this which changes result cardinality.
I ran into a similar issue using version 6.6.11.Final.
I have an entity A, which has a @ManyToMany relation with entity B. The relation is implemented as a two-column table, with uuids of both entities.
Entity A also a has an @ElementCollection field (let’s call it bIds), which is mapped to the same many-to-many table, it is a Set<UUID>, containing the uuids of related B entities.
I need to retrieve entities A using criteria API with these conditions:
they must have a relation to at least one of the Bs with ids from the supplied Collection<UUID> bIds
their bIds must be fetched
Now, the straightforward option of root.get("bIds").in(bIds) doesn’t work due to the the exception from above.
Replacing get with a join works, but since you also need a fetch, you end up with 2 of the same join, which, at least in my case, wrecked havoc on query plan and performance (and is also just ugly).
What I ended up doing is a fetch which is then casted to a Join, so I only get a single join. I undestand that this is a shortcoming of the JPA itself, but at least before this change you didn’t have to scratch your head dealing with either two joins or casts, you could traverse the attribute like any other.
Also, I’m not sure if you can use member of with a multi-valued argument, like you can do with in operator, so this looks like a functional regression.