DATAJPA-44 - Adapted changes in Spring Data Commons Core.

Added unit tests to ensure correct named query name.
This commit is contained in:
Oliver Gierke
2011-04-05 11:00:43 +02:00
parent 2959881df5
commit c2b7047c71
9 changed files with 105 additions and 48 deletions

View File

@@ -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();
}

View File

@@ -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!");

View File

@@ -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);
}

View File

@@ -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

View File

@@ -0,0 +1,8 @@
package org.springframework.data.jpa.domain.sample;
/**
* @author Oliver Gierke
*/
public class SpecialUser extends User {
}

View File

@@ -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 {

View File

@@ -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<QueryHint> 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.
*

View File

@@ -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);
}

View File

@@ -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<User, Integer>,
List<User> findByEmailAddressLike(String email, Sort sort);
List<SpecialUser> findSpecialUsersByLastname(String lastname);
}