From 71234d90aed88ca7c25b413f135253f5248d9398 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Mon, 1 Apr 2024 16:56:22 +0800 Subject: [PATCH] HHH-17912 Disallow multiple valued binding for BasicCollectionType --- .../sqm/internal/DomainParameterXref.java | 4 ++++ .../MultiTypedBasicAttributesEntity.java | 12 ++++++++++ .../orm/test/jpa/criteria/ParameterTest.java | 22 +++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java index c91606f87f..18211c89f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/DomainParameterXref.java @@ -22,6 +22,7 @@ import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter; import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper; import org.hibernate.query.sqm.tree.expression.SqmParameter; +import org.hibernate.type.BasicCollectionType; /** * Maintains a cross-reference between SqmParameter and QueryParameter references. @@ -90,6 +91,9 @@ else if ( sqmParameter.getPosition() != null ) { queryParameter.disallowMultiValuedBinding(); } } + else if ( sqmParameter.getExpressible() != null && sqmParameter.getExpressible().getSqmType() instanceof BasicCollectionType ) { + queryParameter.disallowMultiValuedBinding(); + } sqmParamsByQueryParam.computeIfAbsent( queryParameter, qp -> new ArrayList<>() ).add( sqmParameter ); queryParamBySqmParam.put( sqmParameter, queryParameter ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/MultiTypedBasicAttributesEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/MultiTypedBasicAttributesEntity.java index f28f5023d0..808884f718 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/MultiTypedBasicAttributesEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/MultiTypedBasicAttributesEntity.java @@ -13,6 +13,8 @@ import org.hibernate.annotations.GenericGenerator; +import java.util.List; + /** * An entity with multiple attributes of basic type for use in testing using those types/attributes * in queries. @@ -29,6 +31,8 @@ public class MultiTypedBasicAttributesEntity { private int[] someInts; private Integer[] someWrappedIntegers; + private List integerList; + public Long getId() { return id; } @@ -52,4 +56,12 @@ public Integer[] getSomeWrappedIntegers() { public void setSomeWrappedIntegers(Integer[] someWrappedIntegers) { this.someWrappedIntegers = someWrappedIntegers; } + + public List getIntegerList() { + return integerList; + } + + public void setIntegerList(List integerList) { + this.integerList = integerList; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/ParameterTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/ParameterTest.java index 8a5dfd0652..f830744f59 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/ParameterTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/ParameterTest.java @@ -16,11 +16,10 @@ import jakarta.persistence.criteria.Root; import java.util.Arrays; +import java.util.List; import java.util.Map; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.dialect.OracleDialect; -import org.hibernate.testing.orm.junit.SkipForDialect; import org.junit.Test; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; @@ -150,6 +149,25 @@ public void testParameterInParameterList2() { } ); } + @Test + @TestForIssue(jiraKey = "HHH-17912") + public void testAttributeEqualListParameter() { + TransactionUtil.doInJPA( this::entityManagerFactory, em -> { + final CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); + final CriteriaQuery criteria = criteriaBuilder + .createQuery( MultiTypedBasicAttributesEntity.class ); + + final ParameterExpression parameter = criteriaBuilder.parameter( List.class ); + + final Root root = criteria.from( MultiTypedBasicAttributesEntity.class ); + criteria.select( root ).where( criteriaBuilder.equal( root.get( MultiTypedBasicAttributesEntity_.integerList ), parameter ) ); + + final TypedQuery query1 = em.createQuery( criteria ); + query1.setParameter( parameter, List.of( 1, 2, 3 ) ); + query1.getResultList(); + } ); + } + @Override public Class[] getAnnotatedClasses() { return new Class[] { MultiTypedBasicAttributesEntity.class };