Criteria isMember() doesn't work with collections mapped as array
Description
Activity

Christian Beikov 4 days ago
Look at the method signatures of the CriteriaBuilder.In
type, this wouldn’t work unless you do unchecked casts.
I can imagine supporting collections for the isMember
/isNotMember
methods, because the Java generics would work out, but arrays wouldn’t work without unsafe casts.
Overall, I think it’s simply better to rely on the dedicated methods arrayContains()
/collectionContains()
. With respect to bugs related to enum collections, lets discuss that on https://hibernate.atlassian.net/browse/HHH-19294.

Pavel Hrabec 4 days ago
Is this behavior something that is expected in the longer term? From the user PoV it is a bit confusing that a collection mapped using @ElementCollection
is supported by isMember()
but a collection mapped as an array is not.
Anyway, I’ve encountered another issue affecting the usage of array/collectionContains()
with enums: https://hibernate.atlassian.net/browse/HHH-19294

Christian Beikov 4 days ago
To check if an expression is contained in an array, you have to use HibernateCriteriaBuilder.arrayContains()
. In HQL we have syntax sugar that allows to use where 'label' in e.labels
, but that is just for HQL. Also see https://in.relation.to/2024/08/08/orm-660/#array-syntax-sugar and https://docs.jboss.org/hibernate/orm/6.6/userguide/html_single/Hibernate_User_Guide.html#hql-array-contains-functions

Gavin King 4 days ago
I don’t think this is supposed to work. I think you’re supposed to use HibernateCriteriaBuilder.in()
. Is that correct, @Christian Beikov ?
Details
Assignee
UnassignedUnassignedReporter
Pavel HrabecPavel HrabecAffects versions
Priority
Major
Details
Details
Assignee
Reporter

Given the following entity:
public class EntityWithArray { ... @Column(name = "labels") private Set<String> labels = new HashSet<>();
I would expect that
CriteriaBuilder#isMember()
would work:var cb = em.getCriteriaBuilder(); var cq = cb.createQuery(EntityWithArray.class); var root = cq.from(EntityWithArray.class); cq.where(cb.isMember("label", root.get("labels")));
However, this fails with an exception:
org.hibernate.query.SemanticException: Operand of 'member of' operator must be a plural path at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.createSqmMemberOfPredicate(SqmCriteriaNodeBuilder.java:2725) at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.isMember(SqmCriteriaNodeBuilder.java:2707)
Reproducer: https://github.com/hibernate/hibernate-orm/pull/9918