From f3c138258bd88e787bc965c99e2be04c9e5c4a71 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 16 Apr 2018 16:29:50 +0200 Subject: [PATCH] DATACMNS-1300 - Improved collection query detection for Iterables. Previously a custom Iterable implementation would've caused QueryMethod.isCollectionQuery() to return true. We now solely rely on TypeInformation.isCollectionLike() (which checks for exact Iterable, Collection assignability and arrays) after handling potential wrapper types. --- .../data/repository/query/QueryMethod.java | 15 +++++++------- .../query/QueryMethodUnitTests.java | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index f9f782944..56f8fd2a7 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -154,7 +154,8 @@ public class QueryMethod { Class methodDomainClass = metadata.getReturnedDomainClass(method); this.domainClass = repositoryDomainClass == null || repositoryDomainClass.isAssignableFrom(methodDomainClass) - ? methodDomainClass : repositoryDomainClass; + ? methodDomainClass + : repositoryDomainClass; } return domainClass; @@ -186,13 +187,11 @@ public class QueryMethod { return true; } - if (QueryExecutionConverters.supports(unwrappedReturnType) - && QueryExecutionConverters.isSingleValue(unwrappedReturnType)) { - return false; + if (QueryExecutionConverters.supports(unwrappedReturnType)) { + return !QueryExecutionConverters.isSingleValue(unwrappedReturnType); } - return org.springframework.util.ClassUtils.isAssignable(Iterable.class, unwrappedReturnType) - || unwrappedReturnType.isArray(); + return ClassTypeInformation.from(unwrappedReturnType).isCollectionLike(); } /** @@ -285,7 +284,9 @@ public class QueryMethod { Assert.notEmpty(types, "Types must not be null or empty!"); TypeInformation returnType = ClassTypeInformation.fromReturnTypeOf(method); - returnType = QueryExecutionConverters.isSingleValue(returnType.getType()) ? returnType.getComponentType() + + returnType = QueryExecutionConverters.isSingleValue(returnType.getType()) // + ? returnType.getComponentType() // : returnType; for (Class type : types) { diff --git a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java index 61b9bd360..21147d383 100644 --- a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java @@ -38,6 +38,7 @@ import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.AbstractRepositoryMetadata; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.util.Version; @@ -221,6 +222,15 @@ public class QueryMethodUnitTests { assertThat(new QueryMethod(method, repositoryMetadata, factory).isCollectionQuery(), is(true)); } + @Test // DATACMNS-1300 + public void doesNotConsiderMethodForIterableAggregateACollectionQuery() throws Exception { + + RepositoryMetadata metadata = AbstractRepositoryMetadata.getMetadata(ContainerRepository.class); + Method method = ContainerRepository.class.getMethod("someMethod"); + + assertThat(new QueryMethod(method, metadata, factory).isCollectionQuery(), is(false)); + } + interface SampleRepository extends Repository { String pagingMethodWithInvalidReturnType(Pageable pageable); @@ -274,4 +284,14 @@ public class QueryMethodUnitTests { class SpecialUser extends User { } + + // DATACMNS-1300 + + class Element {} + + abstract class Container implements Iterable {} + + interface ContainerRepository extends Repository { + Container someMethod(); + } }