diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java index 3a33ae380..479dc4b52 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/PartTreeJpaQuery.java @@ -166,10 +166,14 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { JpaParameter parameter = parameters.getBindableParameter(index); - if (expectsCollection(type) && !parameterIsCollectionLike(parameter)) { - throw new IllegalStateException(wrongParameterTypeMessage(methodName, property, type, "Collection", parameter)); - } else if (!expectsCollection(type) && !parameterIsScalarLike(parameter)) { - throw new IllegalStateException(wrongParameterTypeMessage(methodName, property, type, "scalar", parameter)); + if (expectsCollection(type)) { + if (!parameterIsCollectionLike(parameter)) { + throw new IllegalStateException(wrongParameterTypeMessage(methodName, property, type, "Collection", parameter)); + } + } else { + if (!part.getProperty().isCollection() && !parameterIsScalarLike(parameter)) { + throw new IllegalStateException(wrongParameterTypeMessage(methodName, property, type, "scalar", parameter)); + } } } @@ -319,7 +323,7 @@ public class PartTreeJpaQuery extends AbstractJpaQuery { returnedType = processor.getReturnedType(); } - if (accessor != null && accessor.getScrollPosition()instanceof KeysetScrollPosition keyset) { + if (accessor != null && accessor.getScrollPosition() instanceof KeysetScrollPosition keyset) { return new JpaKeysetScrollQueryCreator(tree, returnedType, builder, provider, entityInformation, keyset); } diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java index dfc5eee69..7a4fed2ea 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java @@ -39,7 +39,16 @@ import jakarta.persistence.metamodel.SingularAttribute; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Member; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -568,7 +577,7 @@ public abstract class QueryUtils { * * @param originalQuery must not be {@literal null} or empty. * @return Guaranteed to be not {@literal null}. - * @deprecated use {@link DeclaredQuery#deriveCountQuery(String, String)} instead. + * @deprecated use {@link DeclaredQuery#deriveCountQuery(String)} instead. */ @Deprecated public static String createCountQueryFor(String originalQuery) { @@ -582,7 +591,7 @@ public abstract class QueryUtils { * @param countProjection may be {@literal null}. * @return a query String to be used a count query for pagination. Guaranteed to be not {@literal null}. * @since 1.6 - * @deprecated use {@link DeclaredQuery#deriveCountQuery(String, String)} instead. + * @deprecated use {@link DeclaredQuery#deriveCountQuery(String)} instead. */ @Deprecated public static String createCountQueryFor(String originalQuery, @Nullable String countProjection) { diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java index b61350411..ddd71dbfa 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java @@ -30,6 +30,7 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.Set; import org.hibernate.Version; import org.junit.jupiter.api.BeforeEach; @@ -228,6 +229,13 @@ class PartTreeJpaQueryIntegrationTests { .withMessageContaining("UserRepository"); // the repository } + @Test // GH-3356 + void allowsCollectionArgForCollectionProperty() throws Exception { + + new PartTreeJpaQuery(getQueryMethod("findByAttributes", Set.class), entityManager); + new PartTreeJpaQuery(getQueryMethod("findByAttributes", String[].class), entityManager); + } + private void testIgnoreCase(String methodName, Object... values) throws Exception { Class[] parameterTypes = new Class[values.length]; @@ -297,6 +305,10 @@ class PartTreeJpaQueryIntegrationTests { // Wrong property name User findByNoSuchProperty(String x); + + List findByAttributes(Set attributes); + + List findByAttributes(String... attributes); } }