diff --git a/pom.xml b/pom.xml
index 0ee6e9e..08145b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data.build
spring-data-parent
1.8.0.BUILD-SNAPSHOT
- ../spring-data-build/parent/pom.xml
+
@@ -49,7 +49,7 @@
joda-time
joda-time
- 2.5
+ ${jodatime}
test
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java
index efa7b27..e53f4e9 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.lang.reflect.Constructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
import org.springframework.data.keyvalue.core.IterableConverter;
import org.springframework.data.keyvalue.core.KeyValueOperations;
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
@@ -28,10 +29,12 @@ import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
+import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpression;
+import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -50,25 +53,58 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
private KeyValueQuery> query;
- public KeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evalContextProvider,
+ /**
+ * Creates a new {@link KeyValuePartTreeQuery} for the given {@link QueryMethod}, {@link EvaluationContextProvider},
+ * {@link KeyValueOperations} and query creator type.
+ *
+ * @param queryMethod must not be {@literal null}.
+ * @param evaluationContextProvider must not be {@literal null}.
+ * @param keyValueOperations must not be {@literal null}.
+ * @param queryCreator must not be {@literal null}.
+ */
+ public KeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evaluationContextProvider,
KeyValueOperations keyValueOperations, Class extends AbstractQueryCreator, ?>> queryCreator) {
+ Assert.notNull(queryMethod, "Query method must not be null!");
+ Assert.notNull(evaluationContextProvider, "EvaluationContextprovider must not be null!");
+ Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
+ Assert.notNull(queryCreator, "QueryCreator type must not be null!");
+
this.queryMethod = queryMethod;
this.keyValueOperations = keyValueOperations;
- this.evaluationContextProvider = evalContextProvider;
+ this.evaluationContextProvider = evaluationContextProvider;
this.queryCreator = queryCreator;
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
+ */
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
+ */
@Override
public Object execute(Object[] parameters) {
- KeyValueQuery> query = prepareQuery(parameters);
+ ParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters);
+ KeyValueQuery> query = prepareQuery(parameters, accessor);
+ ResultProcessor processor = queryMethod.getResultProcessor().withDynamicProjection(accessor);
+
+ return processor.processResult(doExecute(parameters, query));
+ }
+
+ /**
+ * @param parameters
+ * @param query
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Object doExecute(Object[] parameters, KeyValueQuery> query) {
if (queryMethod.isPageQuery() || queryMethod.isSliceQuery()) {
@@ -78,8 +114,8 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
Iterable> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
- long count = queryMethod.isSliceQuery() ? 0 : keyValueOperations.count(query, queryMethod.getEntityInformation()
- .getJavaType());
+ long count = queryMethod.isSliceQuery() ? 0
+ : keyValueOperations.count(query, queryMethod.getEntityInformation().getJavaType());
return new PageImpl(IterableConverter.toList(result), page, count);
@@ -91,16 +127,13 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
Iterable> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
return result.iterator().hasNext() ? result.iterator().next() : null;
-
}
throw new UnsupportedOperationException("Query method not supported.");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
- private KeyValueQuery> prepareQuery(Object[] parameters) {
-
- ParametersParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters);
+ private KeyValueQuery> prepareQuery(Object[] parameters, ParameterAccessor accessor) {
if (this.query == null) {
this.query = createQuery(accessor);
@@ -116,11 +149,9 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
q.setRows(-1);
}
- if (accessor.getSort() != null) {
- q.setSort(accessor.getSort());
- } else {
- q.setSort(this.query.getSort());
- }
+ Sort sort = accessor.getSort();
+
+ q.setSort(sort != null ? sort : query.getSort());
if (q.getCritieria() instanceof SpelExpression) {
EvaluationContext context = this.evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(),
@@ -131,7 +162,7 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
return q;
}
- public KeyValueQuery> createQuery(ParametersParameterAccessor accessor) {
+ public KeyValueQuery> createQuery(ParameterAccessor accessor) {
PartTree tree = new PartTree(getQueryMethod().getName(), getQueryMethod().getEntityInformation().getJavaType());
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java
index 919b50c..54c34c7 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactory.java
@@ -25,6 +25,7 @@ import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
+import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.NamedQueries;
@@ -170,13 +171,15 @@ public class KeyValueRepositoryFactory extends RepositoryFactorySupport {
this.queryCreator = queryCreator;
}
- /*
+ /*
* (non-Javadoc)
- * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.repository.core.NamedQueries)
+ * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
*/
- public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
+ @Override
+ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
+ NamedQueries namedQueries) {
- QueryMethod queryMethod = new QueryMethod(method, metadata);
+ QueryMethod queryMethod = new QueryMethod(method, metadata, factory);
return new KeyValuePartTreeQuery(queryMethod, evaluationContextProvider, this.keyValueOperations,
this.queryCreator);
}
diff --git a/src/test/java/org/springframework/data/keyvalue/core/SpelQueryEngineUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/SpelQueryEngineUnitTests.java
index fe15fd5..a27b058 100644
--- a/src/test/java/org/springframework/data/keyvalue/core/SpelQueryEngineUnitTests.java
+++ b/src/test/java/org/springframework/data/keyvalue/core/SpelQueryEngineUnitTests.java
@@ -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 query = creator.createQuery();
query.getCritieria().setEvaluationContext(new StandardEvaluationContext(args));
diff --git a/src/test/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreatorUnitTests.java b/src/test/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreatorUnitTests.java
index 20c0a61..e4a4b38 100644
--- a/src/test/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreatorUnitTests.java
+++ b/src/test/java/org/springframework/data/keyvalue/repository/query/SpelQueryCreatorUnitTests.java
@@ -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 q = creator.createQuery();
q.getCritieria().setEvaluationContext(new StandardEvaluationContext(args));
diff --git a/src/test/java/org/springframework/data/map/AbstractRepositoryUnitTests.java b/src/test/java/org/springframework/data/map/AbstractRepositoryUnitTests.java
index 3e2d7de..1a9e869 100644
--- a/src/test/java/org/springframework/data/map/AbstractRepositoryUnitTests.java
+++ b/src/test/java/org/springframework/data/map/AbstractRepositoryUnitTests.java
@@ -155,6 +155,34 @@ public abstract class AbstractRepositoryUnitTests 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 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, KeyValueRepository {
@@ -173,6 +201,13 @@ public abstract class AbstractRepositoryUnitTests findByAgeGreaterThanOrderByAgeAscFirstnameDesc(int age);
+ List findByAgeGreaterThan(int age, Sort sort);
+
+ List findByAgeGreaterThan(int age, Sort sort, Class projectionType);
}
+ interface PersonSummary {
+
+ String getFirstname();
+ }
}