diff --git a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java index da4c5e92b..64b495f9c 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java @@ -24,7 +24,6 @@ import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEnt import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.QueryMethod; import org.springframework.data.repository.query.RepositoryQuery; -import org.springframework.data.repository.support.EntityMetadata; import org.springframework.util.Assert; @@ -109,9 +108,8 @@ public abstract class AbstractJpaQuery implements RepositoryQuery { case PAGING: return new PagedExecution(getParameters()); case MODIFYING: - EntityMetadata metadata = method.getEntityInformation(); return method.getClearAutomatically() ? new ModifyingExecution( - metadata, em) : new ModifyingExecution(metadata, null); + method, em) : new ModifyingExecution(method, null); default: return new SingleEntityExecution(); } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java index 01a181367..947345d6f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryExecution.java @@ -25,7 +25,6 @@ import org.springframework.data.repository.query.ParameterAccessor; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.ParametersParameterAccessor; import org.springframework.data.repository.query.QueryMethod; -import org.springframework.data.repository.support.EntityMetadata; import org.springframework.util.Assert; @@ -218,13 +217,16 @@ public abstract class JpaQueryExecution { * * @param em */ - public ModifyingExecution(EntityMetadata metadata, EntityManager em) { + public ModifyingExecution(JpaQueryMethod method, EntityManager em) { - Class type = metadata.getJavaType(); + Class returnType = method.getReturnType(); - boolean isVoid = void.class.equals(type) || Void.class.equals(type); + boolean isVoid = + void.class.equals(returnType) + || Void.class.equals(returnType); boolean isInt = - int.class.equals(type) || Integer.class.equals(type); + int.class.equals(returnType) + || Integer.class.equals(returnType); Assert.isTrue(isInt || isVoid, "Modifying queries can only use void or int/Integer as return type!"); diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java index d6dd1519d..8d7d1170c 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java @@ -23,6 +23,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.QueryLookupStrategy; import org.springframework.data.repository.query.QueryLookupStrategy.Key; import org.springframework.data.repository.query.RepositoryQuery; +import org.springframework.data.repository.support.RepositoryMetadata; /** @@ -68,9 +69,10 @@ public final class JpaQueryLookupStrategy { * #resolveQuery(org.springframework.data.repository.query.QueryMethod) */ public final RepositoryQuery resolveQuery(Method method, - Class domainClass) { + RepositoryMetadata metadata) { - return resolveQuery(new JpaQueryMethod(method, provider), em); + return resolveQuery(new JpaQueryMethod(method, metadata, provider), + em); } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 9055843e4..3d07dc144 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -30,6 +30,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.QueryHints; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.QueryMethod; +import org.springframework.data.repository.support.RepositoryMetadata; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -52,9 +53,10 @@ public class JpaQueryMethod extends QueryMethod { * @param extractor must not be {@literal null} * @param metadata must not be {@literal null} */ - public JpaQueryMethod(Method method, QueryExtractor extractor) { + public JpaQueryMethod(Method method, RepositoryMetadata metadata, + QueryExtractor extractor) { - super(method); + super(method, metadata); Assert.notNull(method, "Method must not be null!"); Assert.notNull(extractor, "Query extractor must not be null!"); @@ -129,6 +131,17 @@ public class JpaQueryMethod extends QueryMethod { } + /** + * Returns the actual return type of the method. + * + * @return + */ + Class getReturnType() { + + return method.getReturnType(); + } + + /** * Returns the query string declared in a {@link Query} annotation or * {@literal null} if neither the annotation found nor the attribute was diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/SpecialUser.java b/src/test/java/org/springframework/data/jpa/domain/sample/SpecialUser.java new file mode 100644 index 000000000..c0e9a9772 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/SpecialUser.java @@ -0,0 +1,8 @@ +package org.springframework.data.jpa.domain.sample; + +/** + * @author Oliver Gierke + */ +public class SpecialUser extends User { + +} diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java index 35f13cffd..9f2fd1fd3 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryExecutionUnitTests.java @@ -28,9 +28,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.OngoingStubbing; import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution; -import org.springframework.data.repository.support.EntityMetadata; /** @@ -50,7 +48,7 @@ public class JpaQueryExecutionUnitTests { @Mock Query query; @Mock - EntityMetadata metadata; + JpaQueryMethod method; @Test(expected = IllegalArgumentException.class) @@ -100,46 +98,41 @@ public class JpaQueryExecutionUnitTests { @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) public void modifyingExecutionClearsEntityManagerIfSet() { Query param = any(); when(binder.bind(param)).thenReturn(query); when(query.executeUpdate()).thenReturn(0); - mock(metadata, void.class); + when(method.getReturnType()).thenReturn((Class) void.class); - ModifyingExecution execution = new ModifyingExecution(metadata, em); + ModifyingExecution execution = new ModifyingExecution(method, em); execution.execute(jpaQuery, binder); verify(em, times(1)).clear(); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void mock(EntityMetadata method, Class type, - Class... others) { - - OngoingStubbing stubbing = when(method.getJavaType()); - stubbing.thenReturn(type); - } - - @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) public void allowsMethodReturnTypesForModifyingQuery() throws Exception { - mock(metadata, void.class, int.class, Integer.class); + when(method.getReturnType()).thenReturn((Class) void.class, + (Class) int.class, (Class) Integer.class); - new ModifyingExecution(metadata, em); - new ModifyingExecution(metadata, em); - new ModifyingExecution(metadata, em); + new ModifyingExecution(method, em); + new ModifyingExecution(method, em); + new ModifyingExecution(method, em); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test(expected = IllegalArgumentException.class) public void modifyingExecutionRejectsNonIntegerOrVoidReturnType() throws Exception { - mock(metadata, Long.class); - new ModifyingExecution(metadata, em); + when(method.getReturnType()).thenReturn((Class) Long.class); + new ModifyingExecution(method, em); } static class StubQueryExecution extends JpaQueryExecution { diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java index 728b4ddd1..79473fd05 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java @@ -37,6 +37,8 @@ import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.sample.UserRepository; import org.springframework.data.repository.query.QueryMethod; import org.springframework.data.repository.query.QueryMethod.Type; +import org.springframework.data.repository.support.DefaultRepositoryMetadata; +import org.springframework.data.repository.support.RepositoryMetadata; /** @@ -52,6 +54,8 @@ public class JpaQueryMethodUnitTests { @Mock QueryExtractor extractor; + @Mock + RepositoryMetadata metadata; Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, modifyingMethod; @@ -88,7 +92,8 @@ public class JpaQueryMethodUnitTests { @Test public void testname() { - JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor); + JpaQueryMethod method = + new JpaQueryMethod(repositoryMethod, metadata, extractor); assertEquals("User.findByLastname", method.getNamedQueryName()); assertThat(method.getType(), is(Type.COLLECTION)); @@ -98,21 +103,22 @@ public class JpaQueryMethodUnitTests { @Test(expected = IllegalArgumentException.class) public void preventsNullRepositoryMethod() { - new JpaQueryMethod(null, extractor); + new JpaQueryMethod(null, metadata, extractor); } @Test(expected = IllegalArgumentException.class) public void preventsNullQueryExtractor() { - new JpaQueryMethod(repositoryMethod, null); + new JpaQueryMethod(repositoryMethod, metadata, null); } @Test public void returnsCorrectName() { - JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor); + JpaQueryMethod method = + new JpaQueryMethod(repositoryMethod, metadata, extractor); assertEquals(repositoryMethod.getName(), method.getName()); } @@ -120,7 +126,8 @@ public class JpaQueryMethodUnitTests { @Test public void returnsQueryIfAvailable() throws Exception { - JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor); + JpaQueryMethod method = + new JpaQueryMethod(repositoryMethod, metadata, extractor); assertNull(method.getAnnotatedQuery()); @@ -128,7 +135,7 @@ public class JpaQueryMethodUnitTests { UserRepository.class.getMethod("findByAnnotatedQuery", String.class); - assertNotNull(new JpaQueryMethod(repositoryMethod, extractor) + assertNotNull(new JpaQueryMethod(repositoryMethod, metadata, extractor) .getAnnotatedQuery()); } @@ -136,28 +143,28 @@ public class JpaQueryMethodUnitTests { @Test(expected = IllegalStateException.class) public void rejectsInvalidReturntypeOnPagebleFinder() { - new JpaQueryMethod(invalidReturnType, extractor); + new JpaQueryMethod(invalidReturnType, metadata, extractor); } @Test(expected = IllegalStateException.class) public void rejectsPageableAndSortInFinderMethod() { - new JpaQueryMethod(pageableAndSort, extractor); + new JpaQueryMethod(pageableAndSort, metadata, extractor); } @Test(expected = IllegalStateException.class) public void rejectsTwoPageableParameters() { - new JpaQueryMethod(pageableTwice, extractor); + new JpaQueryMethod(pageableTwice, metadata, extractor); } @Test(expected = IllegalStateException.class) public void rejectsTwoSortableParameters() { - new JpaQueryMethod(sortableTwice, extractor); + new JpaQueryMethod(sortableTwice, metadata, extractor); } @@ -171,14 +178,15 @@ public class JpaQueryMethodUnitTests { when(extractor.canExtractQuery()).thenReturn(false); - new JpaQueryMethod(method, extractor); + new JpaQueryMethod(method, metadata, extractor); } @Test public void recognizesModifyingMethod() { - JpaQueryMethod method = new JpaQueryMethod(modifyingMethod, extractor); + JpaQueryMethod method = + new JpaQueryMethod(modifyingMethod, metadata, extractor); assertTrue(method.isModifyingQuery()); } @@ -190,7 +198,7 @@ public class JpaQueryMethodUnitTests { InvalidRepository.class.getMethod("updateMethod", String.class, Pageable.class); - new JpaQueryMethod(method, extractor); + new JpaQueryMethod(method, metadata, extractor); } @@ -201,14 +209,15 @@ public class JpaQueryMethodUnitTests { InvalidRepository.class.getMethod("updateMethod", String.class, Sort.class); - new JpaQueryMethod(method, extractor); + new JpaQueryMethod(method, metadata, extractor); } @Test public void discoversHintsCorrectly() { - JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor); + JpaQueryMethod method = + new JpaQueryMethod(repositoryMethod, metadata, extractor); List hints = method.getHints(); assertNotNull(hints); @@ -216,6 +225,31 @@ public class JpaQueryMethodUnitTests { assertThat(hints.get(0).value(), is("bar")); } + + @Test + public void calculatesNamedQueryNamesCorrectly() throws SecurityException, + NoSuchMethodException { + + JpaQueryMethod queryMethod = + new JpaQueryMethod(repositoryMethod, metadata, extractor); + assertThat(queryMethod.getNamedQueryName(), is("User.findByLastname")); + + RepositoryMetadata metadata = + new DefaultRepositoryMetadata(UserRepository.class); + Method method = + UserRepository.class + .getMethod("renameAllUsersTo", String.class); + queryMethod = new JpaQueryMethod(method, metadata, extractor); + assertThat(queryMethod.getNamedQueryName(), is("User.renameAllUsersTo")); + + method = + UserRepository.class.getMethod("findSpecialUsersByLastname", + String.class); + queryMethod = new JpaQueryMethod(method, metadata, extractor); + assertThat(queryMethod.getNamedQueryName(), + is("SpecialUser.findSpecialUsersByLastname")); + } + /** * Interface to define invalid repository methods for testing. * diff --git a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java index 26e34ee56..b2d153212 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java @@ -33,6 +33,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.jpa.repository.QueryHints; import org.springframework.data.jpa.repository.sample.UserRepository; +import org.springframework.data.repository.support.RepositoryMetadata; /** @@ -51,6 +52,8 @@ public class SimpleJpaQueryUnitTests { QueryExtractor extractor; @Mock Query query; + @Mock + RepositoryMetadata metadata; @Before @@ -61,7 +64,7 @@ public class SimpleJpaQueryUnitTests { Method setUp = UserRepository.class.getMethod("findByLastname", String.class); - method = new JpaQueryMethod(setUp, extractor); + method = new JpaQueryMethod(setUp, metadata, extractor); } diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index 94ddb7f77..e4708384a 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -23,6 +23,7 @@ import javax.persistence.QueryHint; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.sample.SpecialUser; import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -208,4 +209,7 @@ public interface UserRepository extends JpaRepository, List findByEmailAddressLike(String email, Sort sort); + + + List findSpecialUsersByLastname(String lastname); }