DATAKV-121 - Added support for projections on repository query methods.

Repository methods can now return interfaces that act as projections on the original entity instances stored in the repository.

Related ticket: DATACMNS-89.
This commit is contained in:
Oliver Gierke
2015-12-14 18:29:26 +01:00
parent e7efe2912c
commit d1df6d5e76
6 changed files with 103 additions and 29 deletions

View File

@@ -35,6 +35,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
@@ -100,11 +101,12 @@ public class SpelQueryEngineUnitTests {
}
Method method = PersonRepository.class.getMethod(methodName, types.toArray(new Class<?>[types.size()]));
RepositoryMetadata metadata = mock(RepositoryMetadata.class);
doReturn(method.getReturnType()).when(metadata).getReturnedDomainClass(method);
PartTree partTree = new PartTree(method.getName(), method.getReturnType());
SpelQueryCreator creator = new SpelQueryCreator(partTree,
new ParametersParameterAccessor(new QueryMethod(method, metadata).getParameters(), args));
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(
new QueryMethod(method, metadata, new SpelAwareProxyProjectionFactory()).getParameters(), args));
KeyValueQuery<SpelExpression> query = creator.createQuery();
query.getCritieria().setEvaluationContext(new StandardEvaluationContext(args));

View File

@@ -17,6 +17,7 @@ package org.springframework.data.keyvalue.repository.query;
import static org.hamcrest.core.Is.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.util.Date;
@@ -30,6 +31,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
@@ -238,7 +240,7 @@ public class SpelQueryCreatorUnitTests {
* @see DATACMNS-525
*/
@Test
public void greaterThanEaualsReturnsTrueForEqualValues() throws Exception {
public void greaterThanEqualsReturnsTrueForEqualValues() throws Exception {
assertThat(evaluate("findByAgeGreaterThanEqual", BRAN.age).against(BRAN), is(true));
}
@@ -394,10 +396,11 @@ public class SpelQueryCreatorUnitTests {
}
Method method = PersonRepository.class.getMethod(methodName, argTypes);
doReturn(Person.class).when(metadataMock).getReturnedDomainClass(method);
PartTree partTree = new PartTree(method.getName(), method.getReturnType());
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(new QueryMethod(method,
metadataMock).getParameters(), args));
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(
new QueryMethod(method, metadataMock, new SpelAwareProxyProjectionFactory()).getParameters(), args));
KeyValueQuery<SpelExpression> q = creator.createQuery();
q.getCritieria().setEvaluationContext(new StandardEvaluationContext(args));

View File

@@ -155,6 +155,34 @@ public abstract class AbstractRepositoryUnitTests<T extends AbstractRepositoryUn
assertThat(result, contains(TYRION, JAIME, CERSEI));
}
/**
* @see DATAKV-121
*/
@Test
public void projectsResultToInterface() {
repository.save(LENNISTERS);
List<PersonSummary> result = repository.findByAgeGreaterThan(0, new Sort("firstname"));
assertThat(result, hasSize(3));
assertThat(result.get(0).getFirstname(), is(CERSEI.getFirstname()));
}
/**
* @see DATAKV-121
*/
@Test
public void projectsResultToDynamicInterface() {
repository.save(LENNISTERS);
List<PersonSummary> result = repository.findByAgeGreaterThan(0, new Sort("firstname"), PersonSummary.class);
assertThat(result, hasSize(3));
assertThat(result.get(0).getFirstname(), is(CERSEI.getFirstname()));
}
protected abstract T getRepository(KeyValueRepositoryFactory factory);
public static interface PersonRepository extends CrudRepository<Person, String>, KeyValueRepository<Person, String> {
@@ -173,6 +201,13 @@ public abstract class AbstractRepositoryUnitTests<T extends AbstractRepositoryUn
List<Person> findByAgeGreaterThanOrderByAgeAscFirstnameDesc(int age);
List<PersonSummary> findByAgeGreaterThan(int age, Sort sort);
<T> List<T> findByAgeGreaterThan(int age, Sort sort, Class<T> projectionType);
}
interface PersonSummary {
String getFirstname();
}
}