diff --git a/pom.xml b/pom.xml
index 70ed6253..68cf2af0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-keyvalue
- 1.1.0.BUILD-SNAPSHOT
+ 1.1.0.DATAKV-112-SNAPSHOT
Spring Data KeyValue
diff --git a/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java
index 2a11a0ab..e76164d5 100644
--- a/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java
+++ b/src/main/java/org/springframework/data/keyvalue/core/AbstractKeyValueAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -57,6 +57,33 @@ protected AbstractKeyValueAdapter(QueryEngine extends KeyValueAdapter, ?, ?> e
return engine;
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.keyvalue.core.KeyValueAdapter#get(java.io.Serializable, java.io.Serializable, java.lang.Class)
+ */
+ @Override
+ public T get(Serializable id, Serializable keyspace, Class type) {
+ return (T) get(id, keyspace);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.keyvalue.core.KeyValueAdapter#get(java.io.Serializable, java.io.Serializable, java.lang.Class)
+ */
+ @Override
+ public T delete(Serializable id, Serializable keyspace, Class type) {
+ return (T) delete(id, keyspace);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.keyvalue.core.KeyValueAdapter#get(java.io.Serializable, java.io.Serializable, java.lang.Class)
+ */
+ @Override
+ public Iterable find(KeyValueQuery> query, Serializable keyspace, Class type) {
+ return (Iterable) engine.execute(query, keyspace, type);
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#find(org.springframework.data.keyvalue.core.query.KeyValueQuery, java.io.Serializable)
diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java
index 1f47f180..a3bc9347 100644
--- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java
+++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -58,6 +58,15 @@ public interface KeyValueAdapter extends DisposableBean {
*/
Object get(Serializable id, Serializable keyspace);
+ /**
+ * @param id
+ * @param keyspace
+ * @param type
+ * @return
+ * @since 1.1
+ */
+ T get(Serializable id, Serializable keyspace, Class type);
+
/**
* Delete and return the obect with given type and id.
*
@@ -67,6 +76,15 @@ public interface KeyValueAdapter extends DisposableBean {
*/
Object delete(Serializable id, Serializable keyspace);
+ /**
+ * @param id
+ * @param keyspace
+ * @param type
+ * @return
+ * @since 1.1
+ */
+ T delete(Serializable id, Serializable keyspace, Class type);
+
/**
* Get all elements for given keyspace.
*
@@ -76,7 +94,7 @@ public interface KeyValueAdapter extends DisposableBean {
Iterable> getAllOf(Serializable keyspace);
/**
- * Returns a {@link KeyValueIterator} that iterates over all entries.
+ * Returns a {@link CloseableIterator} that iterates over all entries.
*
* @param keyspace
* @return
@@ -104,6 +122,15 @@ public interface KeyValueAdapter extends DisposableBean {
*/
Iterable> find(KeyValueQuery> query, Serializable keyspace);
+ /**
+ * @param query
+ * @param keyspace
+ * @param type
+ * @return
+ * @since 1.1
+ */
+ Iterable find(KeyValueQuery> query, Serializable keyspace, Class type);
+
/**
* Count number of objects within {@literal keyspace}.
*
diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java
index 8d73945f..452fbc69 100644
--- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java
+++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java
@@ -271,7 +271,7 @@ public T findById(final Serializable id, final Class type) {
@Override
public T doInKeyValue(KeyValueAdapter adapter) {
- Object result = adapter.get(id, keyspace);
+ Object result = adapter.get(id, keyspace, type);
if (result == null || typeCheck(type, result)) {
return (T) result;
@@ -342,10 +342,9 @@ public T delete(final Serializable id, final Class type) {
T result = execute(new KeyValueCallback() {
- @SuppressWarnings("unchecked")
@Override
public T doInKeyValue(KeyValueAdapter adapter) {
- return (T) adapter.delete(id, keyspace);
+ return (T) adapter.delete(id, keyspace, type);
}
});
@@ -394,7 +393,7 @@ public Iterable find(final KeyValueQuery> query, final Class type) {
@Override
public Iterable doInKeyValue(KeyValueAdapter adapter) {
- Iterable> result = adapter.find(query, resolveKeySpace(type));
+ Iterable> result = adapter.find(query, resolveKeySpace(type), type);
if (result == null) {
return Collections.emptySet();
}
diff --git a/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java b/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java
index 16c26a8f..ab1dde67 100644
--- a/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java
+++ b/src/main/java/org/springframework/data/keyvalue/core/QueryEngine.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -56,6 +56,21 @@ public Collection> execute(KeyValueQuery> query, Serializable keyspace) {
return execute(criteria, sort, query.getOffset(), query.getRows(), keyspace);
}
+ /**
+ * Extract query attributes and delegate to concrete execution.
+ *
+ * @param query
+ * @param keyspace
+ * @return
+ */
+ public Collection execute(KeyValueQuery> query, Serializable keyspace, Class type) {
+
+ CRITERIA criteria = this.criteriaAccessor != null ? this.criteriaAccessor.resolve(query) : null;
+ SORT sort = this.sortAccessor != null ? this.sortAccessor.resolve(query) : null;
+
+ return execute(criteria, sort, query.getOffset(), query.getRows(), keyspace, type);
+ }
+
/**
* Extract query attributes and delegate to concrete execution.
*
@@ -79,6 +94,21 @@ public long count(KeyValueQuery> query, Serializable keyspace) {
*/
public abstract Collection> execute(CRITERIA criteria, SORT sort, int offset, int rows, Serializable keyspace);
+ /**
+ * @param criteria
+ * @param sort
+ * @param offset
+ * @param rows
+ * @param keyspace
+ * @param type
+ * @return
+ * @since 1.1
+ */
+ public Collection execute(CRITERIA criteria, SORT sort, int offset, int rows, Serializable keyspace,
+ Class type) {
+ return (Collection) execute(criteria, sort, offset, rows, keyspace);
+ }
+
/**
* @param criteria
* @param keyspace
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java
index 30b148ca..4700636e 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -27,6 +27,7 @@
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
import org.springframework.data.keyvalue.repository.KeyValueRepository;
+import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
import org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactoryBean;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
@@ -92,6 +93,7 @@ public void postProcess(BeanDefinitionBuilder builder, AnnotationRepositoryConfi
builder.addPropertyReference("keyValueOperations", attributes.getString(KEY_VALUE_TEMPLATE_BEAN_REF_ATTRIBUTE));
builder.addPropertyValue("queryCreator", getQueryCreatorType(config));
+ builder.addPropertyValue("queryType", getQueryType(config));
builder.addPropertyReference("mappingContext", MAPPING_CONTEXT_BEAN_NAME);
}
@@ -106,16 +108,37 @@ private static Class> getQueryCreatorType(AnnotationRepositoryConfigurationSou
AnnotationMetadata metadata = config.getEnableAnnotationMetadata();
- Map queryCreatorFoo = metadata.getAnnotationAttributes(QueryCreatorType.class.getName());
+ Map queryCreatorAnnotationAttributes = metadata.getAnnotationAttributes(QueryCreatorType.class.getName());
- if (queryCreatorFoo == null) {
+ if (queryCreatorAnnotationAttributes == null) {
return SpelQueryCreator.class;
}
- AnnotationAttributes queryCreatorAttributes = new AnnotationAttributes(queryCreatorFoo);
+ AnnotationAttributes queryCreatorAttributes = new AnnotationAttributes(queryCreatorAnnotationAttributes);
return queryCreatorAttributes.getClass("value");
}
+ /**
+ * Detects the query creator type to be used for the factory to set. Will lookup a {@link QueryCreatorType} annotation
+ * on the {@code @Enable}-annotation or use {@link SpelQueryCreator} if not found.
+ *
+ * @param config
+ * @return
+ */
+ private static Class> getQueryType(AnnotationRepositoryConfigurationSource config) {
+
+ AnnotationMetadata metadata = config.getEnableAnnotationMetadata();
+
+ Map queryCreatorAnnotationAttributes = metadata.getAnnotationAttributes(QueryCreatorType.class.getName());
+
+ if (queryCreatorAnnotationAttributes == null) {
+ return KeyValuePartTreeQuery.class;
+ }
+
+ AnnotationAttributes queryCreatorAttributes = new AnnotationAttributes(queryCreatorAnnotationAttributes);
+ return queryCreatorAttributes.getClass("repositoryQueryType");
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#registerBeansForRoot(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.data.repository.config.RepositoryConfigurationSource)
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/config/QueryCreatorType.java b/src/main/java/org/springframework/data/keyvalue/repository/config/QueryCreatorType.java
index 44b05a27..c464c9dc 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/config/QueryCreatorType.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/config/QueryCreatorType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -21,12 +21,15 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
+import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
/**
* Annotation to customize the query creator type to be used for a specific store.
*
* @author Oliver Gierke
+ * @author Christoph Strobl
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@@ -34,4 +37,12 @@
public @interface QueryCreatorType {
Class extends AbstractQueryCreator, ?>> value();
+
+ /**
+ * The {@link RepositoryQuery} type to be created by the {@link QueryCreatorType#value()}.
+ *
+ * @return
+ * @since 1.1
+ */
+ Class extends RepositoryQuery> repositoryQueryType() default KeyValuePartTreeQuery.class;
}
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java b/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java
new file mode 100644
index 00000000..66fd0981
--- /dev/null
+++ b/src/main/java/org/springframework/data/keyvalue/repository/query/CachingKeyValuePartTreeQuery.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.keyvalue.repository.query;
+
+import org.springframework.data.keyvalue.core.KeyValueOperations;
+import org.springframework.data.keyvalue.core.query.KeyValueQuery;
+import org.springframework.data.repository.query.EvaluationContextProvider;
+import org.springframework.data.repository.query.QueryMethod;
+import org.springframework.data.repository.query.parser.AbstractQueryCreator;
+import org.springframework.data.repository.query.parser.PartTree;
+
+/**
+ * {@link KeyValuePartTreeQuery} implementation deriving queries from {@link PartTree} using a predefined
+ * {@link AbstractQueryCreator} that caches the once created query.
+ *
+ * @author Christoph Strobl
+ * @since 1.1
+ */
+public class CachingKeyValuePartTreeQuery extends KeyValuePartTreeQuery {
+
+ private KeyValueQuery> cachedQuery;
+
+ public CachingKeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evaluationContextProvider,
+ KeyValueOperations keyValueOperations, Class extends AbstractQueryCreator, ?>> queryCreator) {
+ super(queryMethod, evaluationContextProvider, keyValueOperations, queryCreator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery#prepareQuery(java.lang.Object[])
+ */
+ protected KeyValueQuery> prepareQuery(Object[] parameters) {
+
+ if (cachedQuery == null) {
+ cachedQuery = super.prepareQuery(parameters);
+ }
+
+ return prepareQuery(cachedQuery, parameters);
+ }
+}
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 0f920540..8c5e0b9c 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
@@ -52,8 +52,6 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
private final KeyValueOperations keyValueOperations;
private final Class extends AbstractQueryCreator, ?>> queryCreator;
- private KeyValueQuery> query;
-
/**
* Creates a new {@link KeyValuePartTreeQuery} for the given {@link QueryMethod}, {@link EvaluationContextProvider},
* {@link KeyValueOperations} and query creator type.
@@ -77,15 +75,6 @@ public KeyValuePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider
this.queryCreator = queryCreator;
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
- */
- @Override
- public QueryMethod getQueryMethod() {
- return queryMethod;
- }
-
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
@@ -133,23 +122,25 @@ protected Object doExecute(Object[] parameters, KeyValueQuery> query) {
throw new UnsupportedOperationException("Query method not supported.");
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
protected KeyValueQuery> prepareQuery(Object[] parameters) {
- ParametersParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(),
+ return prepareQuery(createQuery(new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters)),
parameters);
+ }
- if (this.query == null) {
- this.query = createQuery(accessor);
- }
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected KeyValueQuery> prepareQuery(KeyValueQuery> instance, Object[] parameters) {
+
+ ParametersParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(),
+ parameters);
- KeyValueQuery> query = new KeyValueQuery(this.query.getCritieria());
+ KeyValueQuery> query = new KeyValueQuery(instance.getCritieria());
- if (this.query.getCritieria() instanceof SpelExpression) {
+ if (instance.getCritieria() instanceof SpelExpression) {
EvaluationContext context = this.evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(),
parameters);
- query = new KeyValueQuery(new SpelCriteria((SpelExpression) this.query.getCritieria(), context));
+ query = new KeyValueQuery(new SpelCriteria((SpelExpression) instance.getCritieria(), context));
}
Pageable pageable = accessor.getPageable();
@@ -157,7 +148,7 @@ protected KeyValueQuery> prepareQuery(Object[] parameters) {
query.setOffset(pageable == null ? -1 : pageable.getOffset());
query.setRows(pageable == null ? -1 : pageable.getPageSize());
- query.setSort(sort == null ? this.query.getSort() : sort);
+ query.setSort(sort == null ? instance.getSort() : sort);
return query;
}
@@ -170,4 +161,13 @@ public KeyValueQuery> createQuery(ParameterAccessor accessor) {
.getConstructorIfAvailable(queryCreator, PartTree.class, ParameterAccessor.class);
return (KeyValueQuery>) BeanUtils.instantiateClass(constructor, tree, accessor).createQuery();
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
+ */
+ @Override
+ public QueryMethod getQueryMethod() {
+ return queryMethod;
+ }
}
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 54c34c7a..c76f0074 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -18,8 +18,10 @@
import static org.springframework.data.querydsl.QueryDslUtils.*;
import java.io.Serializable;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
+import org.springframework.beans.BeanUtils;
import org.springframework.data.keyvalue.core.KeyValueOperations;
import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
@@ -40,6 +42,7 @@
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
/**
* {@link RepositoryFactorySupport} specific of handing
@@ -55,6 +58,7 @@ public class KeyValueRepositoryFactory extends RepositoryFactorySupport {
private final KeyValueOperations keyValueOperations;
private final MappingContext, ?> context;
private final Class extends AbstractQueryCreator, ?>> queryCreator;
+ private final Class extends RepositoryQuery> repositoryQueryType;
/**
* Creates a new {@link KeyValueRepositoryFactory} for the given {@link KeyValueOperations}.
@@ -75,12 +79,29 @@ public KeyValueRepositoryFactory(KeyValueOperations keyValueOperations) {
public KeyValueRepositoryFactory(KeyValueOperations keyValueOperations,
Class extends AbstractQueryCreator, ?>> queryCreator) {
+ this(keyValueOperations, queryCreator, KeyValuePartTreeQuery.class);
+ }
+
+ /**
+ * Creates a new {@link KeyValueRepositoryFactory} for the given {@link KeyValueOperations} and
+ * {@link AbstractQueryCreator}-type.
+ *
+ * @param keyValueOperations must not be {@literal null}.
+ * @param queryCreator must not be {@literal null}.
+ * @param repositoryQueryType must not be {@literal null}.
+ * @since 1.1
+ */
+ public KeyValueRepositoryFactory(KeyValueOperations keyValueOperations,
+ Class extends AbstractQueryCreator, ?>> queryCreator, Class extends RepositoryQuery> repositoryQueryType) {
+
Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreator, "Query creator type must not be null!");
+ Assert.notNull(repositoryQueryType, "RepositoryQueryType type must not be null!");
this.queryCreator = queryCreator;
this.keyValueOperations = keyValueOperations;
this.context = keyValueOperations.getMappingContext();
+ this.repositoryQueryType = repositoryQueryType;
}
/*
@@ -134,7 +155,8 @@ private static boolean isQueryDslRepository(Class> repositoryInterface) {
*/
@Override
protected QueryLookupStrategy getQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider) {
- return new KeyValueQueryLookupStrategy(key, evaluationContextProvider, this.keyValueOperations, this.queryCreator);
+ return new KeyValueQueryLookupStrategy(key, evaluationContextProvider, this.keyValueOperations, this.queryCreator,
+ this.repositoryQueryType);
}
/**
@@ -147,6 +169,7 @@ private static class KeyValueQueryLookupStrategy implements QueryLookupStrategy
private KeyValueOperations keyValueOperations;
private Class extends AbstractQueryCreator, ?>> queryCreator;
+ private Class extends RepositoryQuery> repositoryQueryType;
/**
* Creates a new {@link KeyValueQueryLookupStrategy} for the given {@link Key}, {@link EvaluationContextProvider},
@@ -161,14 +184,29 @@ private static class KeyValueQueryLookupStrategy implements QueryLookupStrategy
*/
public KeyValueQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider,
KeyValueOperations keyValueOperations, Class extends AbstractQueryCreator, ?>> queryCreator) {
+ this(key, evaluationContextProvider, keyValueOperations, queryCreator, KeyValuePartTreeQuery.class);
+ }
+
+ /**
+ * @param key
+ * @param evaluationContextProvider
+ * @param keyValueOperations
+ * @param queryCreator
+ * @since 1.1
+ */
+ public KeyValueQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider,
+ KeyValueOperations keyValueOperations, Class extends AbstractQueryCreator, ?>> queryCreator,
+ Class extends RepositoryQuery> repositoryQueryType) {
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null!");
Assert.notNull(keyValueOperations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreator, "Query creator type must not be null!");
+ Assert.notNull(repositoryQueryType, "RepositoryQueryType type must not be null!");
this.evaluationContextProvider = evaluationContextProvider;
this.keyValueOperations = keyValueOperations;
this.queryCreator = queryCreator;
+ this.repositoryQueryType = repositoryQueryType;
}
/*
@@ -176,11 +214,17 @@ public KeyValueQueryLookupStrategy(Key key, EvaluationContextProvider evaluation
* @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)
*/
@Override
+ @SuppressWarnings("unchecked")
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
NamedQueries namedQueries) {
QueryMethod queryMethod = new QueryMethod(method, metadata, factory);
- return new KeyValuePartTreeQuery(queryMethod, evaluationContextProvider, this.keyValueOperations,
+
+ Constructor extends KeyValuePartTreeQuery> constructor = (Constructor extends KeyValuePartTreeQuery>) ClassUtils
+ .getConstructorIfAvailable(this.repositoryQueryType, QueryMethod.class, EvaluationContextProvider.class,
+ KeyValueOperations.class, Class.class);
+
+ return BeanUtils.instantiateClass(constructor, queryMethod, evaluationContextProvider, this.keyValueOperations,
this.queryCreator);
}
}
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java
index 897cb7be..5c53a84f 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBean.java
@@ -24,6 +24,7 @@
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
+import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.util.Assert;
@@ -33,11 +34,12 @@
* @author Christoph Strobl
* @author Oliver Gierke
*/
-public class KeyValueRepositoryFactoryBean, S, ID extends Serializable> extends
- RepositoryFactoryBeanSupport {
+public class KeyValueRepositoryFactoryBean, S, ID extends Serializable>
+ extends RepositoryFactoryBeanSupport {
private KeyValueOperations operations;
private Class extends AbstractQueryCreator, ?>> queryCreator;
+ private Class extends RepositoryQuery> repositoryQueryType;
/**
* Configures the {@link KeyValueOperations} to be used for the repositories.
@@ -72,27 +74,42 @@ public void setQueryCreator(Class extends AbstractQueryCreator, ?>> queryCre
this.queryCreator = queryCreator;
}
+ /**
+ * Configures the {@link RepositoryQuery} type to be created.
+ *
+ * @param repositoryQueryType must not be {@literal null}.
+ * @since 1.1
+ */
+ public void setQueryType(Class extends RepositoryQuery> repositoryQueryType) {
+
+ Assert.notNull(queryCreator, "Query creator type must not be null!");
+
+ this.repositoryQueryType = repositoryQueryType;
+
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#createRepositoryFactory()
*/
@Override
protected final RepositoryFactorySupport createRepositoryFactory() {
- return createRepositoryFactory(operations, queryCreator);
+ return createRepositoryFactory(operations, queryCreator, repositoryQueryType);
}
/**
* Create the repository factory to be used to create repositories.
- *
+ *
* @param operations will never be {@literal null}.
* @param queryCreator will never be {@literal null}.
+ * @param repositoryQueryType will never be {@literal null}.
* @return must not be {@literal null}.
* @since 1.1
*/
protected KeyValueRepositoryFactory createRepositoryFactory(KeyValueOperations operations,
- Class extends AbstractQueryCreator, ?>> queryCreator) {
+ Class extends AbstractQueryCreator, ?>> queryCreator, Class extends RepositoryQuery> repositoryQueryType) {
- return new KeyValueRepositoryFactory(operations, queryCreator);
+ return new KeyValueRepositoryFactory(operations, queryCreator, repositoryQueryType);
}
/*
@@ -104,6 +121,7 @@ public void afterPropertiesSet() {
Assert.notNull(operations, "KeyValueOperations must not be null!");
Assert.notNull(queryCreator, "Query creator type must not be null!");
+ Assert.notNull(repositoryQueryType, "RepositoryQueryType type type must not be null!");
super.afterPropertiesSet();
}
diff --git a/src/main/java/org/springframework/data/map/repository/config/EnableMapRepositories.java b/src/main/java/org/springframework/data/map/repository/config/EnableMapRepositories.java
index 93072a2c..f8db684a 100644
--- a/src/main/java/org/springframework/data/map/repository/config/EnableMapRepositories.java
+++ b/src/main/java/org/springframework/data/map/repository/config/EnableMapRepositories.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -31,6 +31,7 @@
import org.springframework.data.keyvalue.core.KeyValueOperations;
import org.springframework.data.keyvalue.core.KeyValueTemplate;
import org.springframework.data.keyvalue.repository.config.QueryCreatorType;
+import org.springframework.data.keyvalue.repository.query.CachingKeyValuePartTreeQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
import org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactoryBean;
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
@@ -49,7 +50,7 @@
@Documented
@Inherited
@Import(MapRepositoriesRegistrar.class)
-@QueryCreatorType(SpelQueryCreator.class)
+@QueryCreatorType(value = SpelQueryCreator.class, repositoryQueryType = CachingKeyValuePartTreeQuery.class)
public @interface EnableMapRepositories {
/**
diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java
index 59ee40b7..9c58d595 100644
--- a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java
+++ b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2015 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -212,7 +212,7 @@ public void findByIdShouldReturnObjectWithMatchingIdAndType() {
template.findById("1", Foo.class);
- verify(adapterMock, times(1)).get("1", Foo.class.getName());
+ verify(adapterMock, times(1)).get("1", Foo.class.getName(), Foo.class);
}
/**
@@ -250,7 +250,7 @@ public void findShouldCallFindOnAdapterToResolveMatching() {
template.find(STRING_QUERY, Foo.class);
- verify(adapterMock, times(1)).find(STRING_QUERY, Foo.class.getName());
+ verify(adapterMock, times(1)).find(STRING_QUERY, Foo.class.getName(), Foo.class);
}
/**
@@ -264,7 +264,7 @@ public void findInRangeShouldRespectOffset() {
template.findInRange(1, 5, Foo.class);
- verify(adapterMock, times(1)).find(captor.capture(), eq(Foo.class.getName()));
+ verify(adapterMock, times(1)).find(captor.capture(), eq(Foo.class.getName()), eq(Foo.class));
assertThat(captor.getValue().getOffset(), is(1));
assertThat(captor.getValue().getRows(), is(5));
assertThat(captor.getValue().getCritieria(), nullValue());
@@ -327,7 +327,7 @@ public void deleteShouldRemoveObjectCorrectly() {
template.delete("1", Foo.class);
- verify(adapterMock, times(1)).delete("1", Foo.class.getName());
+ verify(adapterMock, times(1)).delete("1", Foo.class.getName(), Foo.class);
}
/**
@@ -341,7 +341,7 @@ public void deleteRemovesObjectUsingExtractedId() {
template.delete(source);
- verify(adapterMock, times(1)).delete("some-id", ClassWithStringId.class.getName());
+ verify(adapterMock, times(1)).delete("some-id", ClassWithStringId.class.getName(), ClassWithStringId.class);
}
/**
@@ -616,7 +616,7 @@ public void shouldPublishBeforeDeleteEventCorrectly() {
public void shouldPublishAfterDeleteEventCorrectly() {
setEventsToPublish(AfterDeleteEvent.class);
- when(adapterMock.delete(eq("1"), eq(FOO_ONE.getClass().getName()))).thenReturn(FOO_ONE);
+ when(adapterMock.delete(eq("1"), eq(FOO_ONE.getClass().getName()), eq(Foo.class))).thenReturn(FOO_ONE);
template.delete("1", FOO_ONE.getClass());
@@ -663,7 +663,7 @@ public void shouldPublishAfterGetEventCorrectly() {
setEventsToPublish(AfterGetEvent.class);
- when(adapterMock.get(eq("1"), eq(FOO_ONE.getClass().getName()))).thenReturn(FOO_ONE);
+ when(adapterMock.get(eq("1"), eq(FOO_ONE.getClass().getName()), eq(Foo.class))).thenReturn(FOO_ONE);
template.findById("1", FOO_ONE.getClass());
diff --git a/src/test/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBeanUnitTests.java b/src/test/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBeanUnitTests.java
index 0f2d6aad..2d0ea25d 100644
--- a/src/test/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBeanUnitTests.java
+++ b/src/test/java/org/springframework/data/keyvalue/repository/support/KeyValueRepositoryFactoryBeanUnitTests.java
@@ -26,7 +26,9 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.data.keyvalue.core.KeyValueOperations;
+import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
import org.springframework.data.repository.Repository;
+import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
/**
@@ -95,6 +97,7 @@ public void rejectsInstanceWithoutQueryCreator() {
/**
* @see DATAKV-123
+ * @see DATAKV-112
*/
@Test
@SuppressWarnings("unchecked")
@@ -102,9 +105,12 @@ public void initializesConfiguredFactory() {
Class extends AbstractQueryCreator, ?>> creatorType = (Class extends AbstractQueryCreator, ?>>) mock(
AbstractQueryCreator.class).getClass();
+ Class extends RepositoryQuery> queryType = (Class extends RepositoryQuery>) mock(KeyValuePartTreeQuery.class)
+ .getClass();
factoryBean.setQueryCreator(creatorType);
factoryBean.setKeyValueOperations(mock(KeyValueOperations.class));
+ factoryBean.setQueryType(queryType);
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Repository interface");
@@ -121,10 +127,21 @@ public void createsRepositoryFactory() {
Class extends AbstractQueryCreator, ?>> creatorType = (Class extends AbstractQueryCreator, ?>>) mock(
AbstractQueryCreator.class).getClass();
+ Class extends RepositoryQuery> queryType = (Class extends RepositoryQuery>) mock(KeyValuePartTreeQuery.class)
+ .getClass();
factoryBean.setQueryCreator(creatorType);
factoryBean.setKeyValueOperations(mock(KeyValueOperations.class));
+ factoryBean.setQueryType(queryType);
assertThat(factoryBean.createRepositoryFactory(), is(notNullValue()));
}
+
+ /**
+ * @see DATAKV-112
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void rejectsNullQueryType() {
+ factoryBean.setQueryType(null);
+ }
}