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 db5302c..963b50f 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
@@ -16,12 +16,14 @@
package org.springframework.data.keyvalue.repository.support;
import static org.springframework.data.querydsl.QuerydslUtils.*;
+import static org.springframework.data.repository.core.support.RepositoryComposition.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Optional;
import org.springframework.beans.BeanUtils;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.keyvalue.core.KeyValueOperations;
import org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery;
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
@@ -136,8 +138,43 @@ public class KeyValueRepositoryFactory extends RepositoryFactorySupport {
*/
@Override
protected Class> getRepositoryBaseClass(RepositoryMetadata metadata) {
- return isQueryDslRepository(metadata.getRepositoryInterface()) ? QuerydslKeyValueRepository.class
- : SimpleKeyValueRepository.class;
+ return SimpleKeyValueRepository.class;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getRepositoryFragments(org.springframework.data.repository.core.RepositoryMetadata)
+ */
+ @Override
+ protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
+ return getRepositoryFragments(metadata, keyValueOperations);
+ }
+
+ /**
+ * Creates {@link RepositoryFragments} based on {@link RepositoryMetadata} to add Key-Value-specific extensions.
+ * Typically adds a {@link QuerydslMongoPredicateExecutor} if the repository interface uses Querydsl.
+ *
+ * Can be overridden by subclasses to customize {@link RepositoryFragments}.
+ *
+ * @param metadata repository metadata.
+ * @param operations the MongoDB operations manager.
+ * @return
+ * @since 2.6
+ */
+ protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata, KeyValueOperations operations) {
+
+ if (isQueryDslRepository(metadata.getRepositoryInterface())) {
+
+ if (metadata.isReactiveRepository()) {
+ throw new InvalidDataAccessApiUsageException(
+ "Cannot combine Querydsl and reactive repository support in a single interface");
+ }
+
+ return RepositoryFragments
+ .just(new QuerydslKeyValuePredicateExecutor<>(getEntityInformation(metadata.getDomainType()), operations));
+ }
+
+ return RepositoryFragments.empty();
}
/**
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java
new file mode 100644
index 0000000..e4f6b26
--- /dev/null
+++ b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValuePredicateExecutor.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2021 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
+ *
+ * https://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.support;
+
+import static org.springframework.data.keyvalue.repository.support.KeyValueQuerydslUtils.*;
+
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.keyvalue.core.KeyValueOperations;
+import org.springframework.data.querydsl.EntityPathResolver;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.data.querydsl.SimpleEntityPathResolver;
+import org.springframework.data.repository.core.EntityInformation;
+import org.springframework.data.repository.query.FluentQuery;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+
+import com.querydsl.collections.AbstractCollQuery;
+import com.querydsl.collections.CollQuery;
+import com.querydsl.core.NonUniqueResultException;
+import com.querydsl.core.types.EntityPath;
+import com.querydsl.core.types.OrderSpecifier;
+import com.querydsl.core.types.Predicate;
+import com.querydsl.core.types.dsl.PathBuilder;
+
+/**
+ * {@link QuerydslPredicateExecutor} capable of applying {@link Predicate}s using {@link CollQuery}.
+ *
+ * @author Mark Paluch
+ * @since 2.6
+ */
+public class QuerydslKeyValuePredicateExecutor implements QuerydslPredicateExecutor {
+
+ private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
+
+ private final PathBuilder builder;
+ private final Supplier> findAll;
+
+ /**
+ * Creates a new {@link QuerydslKeyValuePredicateExecutor} for the given {@link EntityInformation}.
+ *
+ * @param entityInformation must not be {@literal null}.
+ * @param operations must not be {@literal null}.
+ */
+ public QuerydslKeyValuePredicateExecutor(EntityInformation entityInformation, KeyValueOperations operations) {
+ this(entityInformation, operations, DEFAULT_ENTITY_PATH_RESOLVER);
+ }
+
+ /**
+ * Creates a new {@link QuerydslKeyValuePredicateExecutor} for the given {@link EntityInformation}, and
+ * {@link EntityPathResolver}.
+ *
+ * @param entityInformation must not be {@literal null}.
+ * @param operations must not be {@literal null}.
+ * @param resolver must not be {@literal null}.
+ */
+ public QuerydslKeyValuePredicateExecutor(EntityInformation entityInformation, KeyValueOperations operations,
+ EntityPathResolver resolver) {
+
+ Assert.notNull(resolver, "EntityPathResolver must not be null!");
+
+ EntityPath path = resolver.createPath(entityInformation.getJavaType());
+ this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
+ findAll = () -> operations.findAll(entityInformation.getJavaType());
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findOne(com.querydsl.core.types.Predicate)
+ */
+ @Override
+ public Optional findOne(Predicate predicate) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+
+ try {
+ return Optional.ofNullable(prepareQuery(predicate).fetchOne());
+ } catch (NonUniqueResultException o_O) {
+ throw new IncorrectResultSizeDataAccessException("Expected one or no result but found more than one!", 1, o_O);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.Predicate)
+ */
+ @Override
+ public Iterable findAll(Predicate predicate) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+
+ return prepareQuery(predicate).fetchResults().getResults();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, com.querydsl.core.types.OrderSpecifier[])
+ */
+ @Override
+ public Iterable findAll(Predicate predicate, OrderSpecifier>... orders) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+ Assert.notNull(orders, "OrderSpecifiers must not be null!");
+
+ AbstractCollQuery query = prepareQuery(predicate);
+ query.orderBy(orders);
+
+ return query.fetchResults().getResults();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, org.springframework.data.domain.Sort)
+ */
+ @Override
+ public Iterable findAll(Predicate predicate, Sort sort) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+ Assert.notNull(sort, "Sort must not be null!");
+
+ return findAll(predicate, toOrderSpecifier(sort, builder));
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, org.springframework.data.domain.Pageable)
+ */
+ @Override
+ public Page findAll(Predicate predicate, Pageable pageable) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+ Assert.notNull(pageable, "Pageable must not be null!");
+
+ AbstractCollQuery query = prepareQuery(predicate);
+
+ if (pageable.isPaged() || pageable.getSort().isSorted()) {
+
+ query.offset(pageable.getOffset());
+ query.limit(pageable.getPageSize());
+
+ if (pageable.getSort().isSorted()) {
+ query.orderBy(toOrderSpecifier(pageable.getSort(), builder));
+ }
+ }
+
+ return new PageImpl<>(query.fetchResults().getResults(), pageable, count(predicate));
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.OrderSpecifier[])
+ */
+ @Override
+ public Iterable findAll(OrderSpecifier>... orders) {
+
+ Assert.notNull(orders, "OrderSpecifiers must not be null!");
+
+ if (orders.length == 0) {
+ return findAll.get();
+ }
+
+ AbstractCollQuery query = prepareQuery(null);
+ query.orderBy(orders);
+
+ return query.fetchResults().getResults();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#count(com.querydsl.core.types.Predicate)
+ */
+ @Override
+ public long count(Predicate predicate) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+
+ return prepareQuery(predicate).fetchCount();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#exists(com.querydsl.core.types.Predicate)
+ */
+ @Override
+ public boolean exists(Predicate predicate) {
+
+ Assert.notNull(predicate, "Predicate must not be null!");
+
+ return count(predicate) > 0;
+ }
+
+ @Override
+ public R findBy(Predicate predicate,
+ Function, R> queryFunction) {
+ throw new UnsupportedOperationException("Not yet supported");
+ }
+
+ /**
+ * Creates executable query for given {@link Predicate}.
+ *
+ * @param predicate
+ * @return
+ */
+ protected AbstractCollQuery prepareQuery(@Nullable Predicate predicate) {
+
+ CollQuery query = new CollQuery<>();
+ query.from(builder, findAll.get());
+
+ return predicate != null ? query.where(predicate) : query;
+ }
+}
diff --git a/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValueRepository.java b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValueRepository.java
index dd9f25e..31e4c99 100644
--- a/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValueRepository.java
+++ b/src/main/java/org/springframework/data/keyvalue/repository/support/QuerydslKeyValueRepository.java
@@ -15,14 +15,10 @@
*/
package org.springframework.data.keyvalue.repository.support;
-import static org.springframework.data.keyvalue.repository.support.KeyValueQuerydslUtils.*;
-
import java.util.Optional;
import java.util.function.Function;
-import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.keyvalue.core.KeyValueOperations;
@@ -32,17 +28,11 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.query.FluentQuery;
-import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
-import org.springframework.util.ObjectUtils;
-import com.querydsl.collections.AbstractCollQuery;
import com.querydsl.collections.CollQuery;
-import com.querydsl.core.NonUniqueResultException;
-import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
-import com.querydsl.core.types.dsl.PathBuilder;
/**
* {@link KeyValueRepository} implementation capable of executing {@link Predicate}s using {@link CollQuery}.
@@ -53,13 +43,13 @@ import com.querydsl.core.types.dsl.PathBuilder;
* @author Mark Paluch
* @param the domain type to manage
* @param the identifier type of the domain type
+ * @deprecated since 2.6, use {@link QuerydslKeyValuePredicateExecutor} instead.
*/
+@Deprecated
public class QuerydslKeyValueRepository extends SimpleKeyValueRepository
implements QuerydslPredicateExecutor {
- private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
-
- private final PathBuilder builder;
+ private final QuerydslKeyValuePredicateExecutor executor;
/**
* Creates a new {@link QuerydslKeyValueRepository} for the given {@link EntityInformation} and
@@ -69,7 +59,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
* @param operations must not be {@literal null}.
*/
public QuerydslKeyValueRepository(EntityInformation entityInformation, KeyValueOperations operations) {
- this(entityInformation, operations, DEFAULT_ENTITY_PATH_RESOLVER);
+ this(entityInformation, operations, SimpleEntityPathResolver.INSTANCE);
}
/**
@@ -87,8 +77,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
Assert.notNull(resolver, "EntityPathResolver must not be null!");
- EntityPath path = resolver.createPath(entityInformation.getJavaType());
- this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
+ this.executor = new QuerydslKeyValuePredicateExecutor<>(entityInformation, operations, resolver);
}
/*
@@ -97,14 +86,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Optional findOne(Predicate predicate) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
-
- try {
- return Optional.ofNullable(prepareQuery(predicate).fetchOne());
- } catch (NonUniqueResultException o_O) {
- throw new IncorrectResultSizeDataAccessException("Expected one or no result but found more than one!", 1, o_O);
- }
+ return executor.findOne(predicate);
}
/*
@@ -113,10 +95,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Iterable findAll(Predicate predicate) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
-
- return prepareQuery(predicate).fetchResults().getResults();
+ return executor.findAll(predicate);
}
/*
@@ -125,14 +104,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Iterable findAll(Predicate predicate, OrderSpecifier>... orders) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
- Assert.notNull(orders, "OrderSpecifiers must not be null!");
-
- AbstractCollQuery query = prepareQuery(predicate);
- query.orderBy(orders);
-
- return query.fetchResults().getResults();
+ return executor.findAll(predicate, orders);
}
/*
@@ -141,11 +113,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Iterable findAll(Predicate predicate, Sort sort) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
- Assert.notNull(sort, "Sort must not be null!");
-
- return findAll(predicate, toOrderSpecifier(sort, builder));
+ return executor.findAll(predicate, sort);
}
/*
@@ -154,23 +122,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Page findAll(Predicate predicate, Pageable pageable) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
- Assert.notNull(pageable, "Pageable must not be null!");
-
- AbstractCollQuery query = prepareQuery(predicate);
-
- if (pageable.isPaged() || pageable.getSort().isSorted()) {
-
- query.offset(pageable.getOffset());
- query.limit(pageable.getPageSize());
-
- if (pageable.getSort().isSorted()) {
- query.orderBy(toOrderSpecifier(pageable.getSort(), builder));
- }
- }
-
- return new PageImpl<>(query.fetchResults().getResults(), pageable, count(predicate));
+ return executor.findAll(predicate, pageable);
}
/*
@@ -179,17 +131,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public Iterable findAll(OrderSpecifier>... orders) {
-
- Assert.notNull(orders, "OrderSpecifiers must not be null!");
-
- if (ObjectUtils.isEmpty(orders)) {
- return findAll();
- }
-
- AbstractCollQuery query = prepareQuery(null);
- query.orderBy(orders);
-
- return query.fetchResults().getResults();
+ return executor.findAll(orders);
}
/*
@@ -198,10 +140,7 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public long count(Predicate predicate) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
-
- return prepareQuery(predicate).fetchCount();
+ return executor.count(predicate);
}
/*
@@ -210,29 +149,13 @@ public class QuerydslKeyValueRepository extends SimpleKeyValueRepository<
*/
@Override
public boolean exists(Predicate predicate) {
-
- Assert.notNull(predicate, "Predicate must not be null!");
-
- return count(predicate) > 0;
+ return executor.exists(predicate);
}
@Override
public R findBy(Predicate predicate,
Function, R> queryFunction) {
- throw new UnsupportedOperationException("Not yet supported");
+ return executor.findBy(predicate, queryFunction);
}
- /**
- * Creates executable query for given {@link Predicate}.
- *
- * @param predicate
- * @return
- */
- protected AbstractCollQuery prepareQuery(@Nullable Predicate predicate) {
-
- CollQuery query = new CollQuery<>();
- query.from(builder, findAll());
-
- return predicate != null ? query.where(predicate) : query;
- }
}
diff --git a/src/test/java/org/springframework/data/map/QuerydslKeyValueRepositoryUnitTests.java b/src/test/java/org/springframework/data/map/QuerydslKeyValueRepositoryUnitTests.java
index ca62db3..5976c05 100644
--- a/src/test/java/org/springframework/data/map/QuerydslKeyValueRepositoryUnitTests.java
+++ b/src/test/java/org/springframework/data/map/QuerydslKeyValueRepositoryUnitTests.java
@@ -16,12 +16,10 @@
package org.springframework.data.map;
import static org.assertj.core.api.Assertions.*;
-import static org.assertj.core.api.Assumptions.*;
import java.util.List;
import java.util.Optional;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
@@ -37,7 +35,6 @@ import org.springframework.data.map.QuerydslKeyValueRepositoryUnitTests.QPersonR
import org.springframework.data.querydsl.QSort;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.util.Streamable;
-import org.springframework.data.util.Version;
/**
* Unit tests for {@link QuerydslKeyValueRepository}.
@@ -49,11 +46,6 @@ import org.springframework.data.util.Version;
*/
public class QuerydslKeyValueRepositoryUnitTests extends AbstractRepositoryUnitTests {
- @BeforeEach
- void before() {
- assumeThat(Version.javaVersion().toString()).startsWith("1.8");
- }
-
@Test // DATACMNS-525
void findOneIsExecutedCorrectly() {