DATAMONGO-1702 - Adopt to composable repositories.
Deprecate QuerydslMongoRepository, introduce QuerydslMongoPredicateExecutor instead without extending SimpleMongoRepository. Use RepositoryFragments to mix in requested repository aspects. Original pull request: #480.
This commit is contained in:
committed by
Oliver Gierke
parent
3d623d8181
commit
7526f3bd2e
@@ -36,13 +36,13 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.core.support.RepositoryFragment;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
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.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.data.repository.reactive.RxJava1CrudRepository;
|
||||
import org.springframework.data.repository.util.QueryExecutionConverters;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -88,25 +88,36 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return SimpleMongoRepository.class;
|
||||
}
|
||||
|
||||
boolean isReactiveRepository = (PROJECT_REACTOR_PRESENT
|
||||
&& ReactiveCrudRepository.class.isAssignableFrom(metadata.getRepositoryInterface()))
|
||||
|| (RXJAVA_OBSERVABLE_PRESENT
|
||||
&& RxJava1CrudRepository.class.isAssignableFrom(metadata.getRepositoryInterface()));
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getRepositoryFragments(org.springframework.data.repository.core.RepositoryMetadata)
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
|
||||
|
||||
RepositoryFragments fragments = RepositoryFragments.empty();
|
||||
|
||||
boolean isQueryDslRepository = QUERY_DSL_PRESENT
|
||||
&& QuerydslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface());
|
||||
|
||||
if (isReactiveRepository) {
|
||||
if (isQueryDslRepository) {
|
||||
|
||||
if (isQueryDslRepository) {
|
||||
if (metadata.isReactiveRepository()) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Cannot combine Querydsl and reactive repository in one interface");
|
||||
"Cannot combine Querydsl and reactive repository support in a single interface");
|
||||
}
|
||||
return SimpleReactiveMongoRepository.class;
|
||||
|
||||
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType(),
|
||||
metadata);
|
||||
|
||||
fragments = fragments.append(RepositoryFragment.implemented(
|
||||
getTargetRepositoryViaReflection(QuerydslMongoPredicateExecutor.class, entityInformation, operations)));
|
||||
}
|
||||
|
||||
return isQueryDslRepository ? QuerydslMongoRepository.class : SimpleMongoRepository.class;
|
||||
return fragments;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -140,16 +151,16 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
}
|
||||
|
||||
private <T, ID> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
RepositoryInformation information) {
|
||||
RepositoryMetadata metadata) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass);
|
||||
return MongoEntityInformationSupport.<T, ID> entityInformationFor(entity,
|
||||
information != null ? information.getIdType() : null);
|
||||
metadata != null ? metadata.getIdType() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2017 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.mongodb.repository.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.querydsl.EntityPathResolver;
|
||||
import org.springframework.data.querydsl.QSort;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.querydsl.SimpleEntityPathResolver;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.support.PageableExecutionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.querydsl.core.NonUniqueResultException;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Expression;
|
||||
import com.querydsl.core.types.OrderSpecifier;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.querydsl.core.types.dsl.PathBuilder;
|
||||
import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
|
||||
/**
|
||||
* MongoDB-specific {@link QuerydslPredicateExecutor} that allows execution {@link Predicate}s in various forms.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
*/
|
||||
public class QuerydslMongoPredicateExecutor<T> implements QuerydslPredicateExecutor<T> {
|
||||
|
||||
private final PathBuilder<T> builder;
|
||||
private final EntityInformation<T, ?> entityInformation;
|
||||
private final MongoOperations mongoOperations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslMongoPredicateExecutor} for the given {@link MongoEntityInformation} and
|
||||
* {@link MongoTemplate}. Uses the {@link SimpleEntityPathResolver} to create an {@link EntityPath} for the given
|
||||
* domain class.
|
||||
*
|
||||
* @param entityInformation must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
*/
|
||||
public QuerydslMongoPredicateExecutor(MongoEntityInformation<T, ?> entityInformation,
|
||||
MongoOperations mongoOperations) {
|
||||
this(entityInformation, mongoOperations, SimpleEntityPathResolver.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslMongoPredicateExecutor} for the given {@link MongoEntityInformation},
|
||||
* {@link MongoTemplate} and {@link EntityPathResolver}.
|
||||
*
|
||||
* @param entityInformation must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param resolver must not be {@literal null}.
|
||||
*/
|
||||
public QuerydslMongoPredicateExecutor(MongoEntityInformation<T, ?> entityInformation, MongoOperations mongoOperations,
|
||||
EntityPathResolver resolver) {
|
||||
|
||||
Assert.notNull(resolver, "EntityPathResolver must not be null!");
|
||||
|
||||
EntityPath<T> path = resolver.createPath(entityInformation.getJavaType());
|
||||
|
||||
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
|
||||
this.entityInformation = entityInformation;
|
||||
this.mongoOperations = mongoOperations;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QuerydslPredicateExecutor#findById(com.querydsl.core.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public Optional<T> findOne(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(createQueryFor(predicate).fetchOne());
|
||||
} catch (NonUniqueResultException ex) {
|
||||
throw new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, com.mysema.query.types.OrderSpecifier<?>[])
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(orders, "Order specifiers must not be null!");
|
||||
|
||||
return createQueryFor(predicate).orderBy(orders).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, Sort sort) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
return applySorting(createQueryFor(predicate), sort).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.OrderSpecifier[])
|
||||
*/
|
||||
@Override
|
||||
public Iterable<T> findAll(OrderSpecifier<?>... orders) {
|
||||
|
||||
Assert.notNull(orders, "Order specifiers must not be null!");
|
||||
|
||||
return createQuery().orderBy(orders).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
@Override
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQueryFor(predicate);
|
||||
|
||||
return PageableExecutionUtils.getPage(applyPagination(query, pageable).fetchResults().getResults(), pageable,
|
||||
() -> createQueryFor(predicate).fetchCount());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#count(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public long count(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchCount();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#exists(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchCount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongodbQuery} for the given {@link Predicate}.
|
||||
*
|
||||
* @param predicate
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQueryFor(Predicate predicate) {
|
||||
return createQuery().where(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongodbQuery}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQuery() {
|
||||
return new SpringDataMongodbQuery<T>(mongoOperations, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Pageable} to the given {@link MongodbQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applyPagination(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Pageable pageable) {
|
||||
|
||||
query = query.offset(pageable.getOffset()).limit(pageable.getPageSize());
|
||||
return applySorting(query, pageable.getSort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Sort} to the given {@link MongodbQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applySorting(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Sort sort) {
|
||||
|
||||
// TODO: find better solution than instanceof check
|
||||
if (sort instanceof QSort) {
|
||||
|
||||
List<OrderSpecifier<?>> orderSpecifiers = ((QSort) sort).getOrderSpecifiers();
|
||||
query.orderBy(orderSpecifiers.toArray(new OrderSpecifier<?>[orderSpecifiers.size()]));
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
sort.stream().map(this::toOrder).forEach(it -> query.orderBy(it));
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}.
|
||||
*
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private OrderSpecifier<?> toOrder(Order order) {
|
||||
|
||||
Expression<Object> property = builder.get(order.getProperty());
|
||||
|
||||
return new OrderSpecifier(
|
||||
order.isAscending() ? com.querydsl.core.types.Order.ASC : com.querydsl.core.types.Order.DESC, property);
|
||||
}
|
||||
}
|
||||
@@ -16,33 +16,13 @@
|
||||
package org.springframework.data.mongodb.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.querydsl.EntityPathResolver;
|
||||
import org.springframework.data.querydsl.QSort;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.querydsl.SimpleEntityPathResolver;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.data.repository.support.PageableExecutionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.querydsl.core.NonUniqueResultException;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Expression;
|
||||
import com.querydsl.core.types.OrderSpecifier;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.querydsl.core.types.dsl.PathBuilder;
|
||||
import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
|
||||
/**
|
||||
* Special Querydsl based repository implementation that allows execution {@link Predicate}s in various forms.
|
||||
@@ -51,249 +31,20 @@ import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @deprecated since 2.0. Querydsl execution is now linked via composable repositories and no longer requires to be a
|
||||
* subclass of {@link SimpleMongoRepository}. Use {@link QuerydslMongoPredicateExecutor} for standalone
|
||||
* Querydsl {@link Predicate} execution.
|
||||
*/
|
||||
public class QuerydslMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID>
|
||||
@Deprecated
|
||||
public class QuerydslMongoRepository<T, ID extends Serializable> extends QuerydslMongoPredicateExecutor<T>
|
||||
implements QuerydslPredicateExecutor<T> {
|
||||
|
||||
private final PathBuilder<T> builder;
|
||||
private final EntityInformation<T, ID> entityInformation;
|
||||
private final MongoOperations mongoOperations;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslMongoRepository} for the given {@link EntityMetadata} and {@link MongoTemplate}. Uses
|
||||
* the {@link SimpleEntityPathResolver} to create an {@link EntityPath} for the given domain class.
|
||||
*
|
||||
* @param entityInformation must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
*/
|
||||
public QuerydslMongoRepository(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations) {
|
||||
this(entityInformation, mongoOperations, SimpleEntityPathResolver.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link QuerydslMongoRepository} for the given {@link MongoEntityInformation}, {@link MongoTemplate}
|
||||
* and {@link EntityPathResolver}.
|
||||
*
|
||||
* @param entityInformation must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param resolver must not be {@literal null}.
|
||||
*/
|
||||
public QuerydslMongoRepository(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations,
|
||||
EntityPathResolver resolver) {
|
||||
|
||||
public QuerydslMongoRepository(MongoEntityInformation<T, ?> entityInformation, MongoOperations mongoOperations) {
|
||||
super(entityInformation, mongoOperations);
|
||||
|
||||
Assert.notNull(resolver, "EntityPathResolver must not be null!");
|
||||
|
||||
EntityPath<T> path = resolver.createPath(entityInformation.getJavaType());
|
||||
|
||||
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
|
||||
this.entityInformation = entityInformation;
|
||||
this.mongoOperations = mongoOperations;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QuerydslPredicateExecutor#findById(com.querydsl.core.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public Optional<T> findOne(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(createQueryFor(predicate).fetchOne());
|
||||
} catch (NonUniqueResultException ex) {
|
||||
throw new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, com.mysema.query.types.OrderSpecifier<?>[])
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(orders, "Order specifiers must not be null!");
|
||||
|
||||
return createQueryFor(predicate).orderBy(orders).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, Sort sort) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
return applySorting(createQueryFor(predicate), sort).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.OrderSpecifier[])
|
||||
*/
|
||||
@Override
|
||||
public Iterable<T> findAll(OrderSpecifier<?>... orders) {
|
||||
|
||||
Assert.notNull(orders, "Order specifiers must not be null!");
|
||||
|
||||
return createQuery().orderBy(orders).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
@Override
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQueryFor(predicate);
|
||||
|
||||
return PageableExecutionUtils.getPage(applyPagination(query, pageable).fetchResults().getResults(), pageable,
|
||||
() -> createQueryFor(predicate).fetchCount());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.SimpleMongoRepository#findAll(org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQuery();
|
||||
|
||||
return PageableExecutionUtils.getPage(applyPagination(query, pageable).fetchResults().getResults(), pageable,
|
||||
() -> createQuery().fetchCount());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.SimpleMongoRepository#findAll(org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Sort sort) {
|
||||
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
return applySorting(createQuery(), sort).fetchResults().getResults();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#count(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public long count(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchCount();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#exists(com.mysema.query.types.Predicate)
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(Predicate predicate) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return createQueryFor(predicate).fetchCount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongodbQuery} for the given {@link Predicate}.
|
||||
*
|
||||
* @param predicate
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQueryFor(Predicate predicate) {
|
||||
return createQuery().where(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MongodbQuery}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQuery() {
|
||||
return new SpringDataMongodbQuery<T>(mongoOperations, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Pageable} to the given {@link MongodbQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applyPagination(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Pageable pageable) {
|
||||
|
||||
query = query.offset(pageable.getOffset()).limit(pageable.getPageSize());
|
||||
return applySorting(query, pageable.getSort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Sort} to the given {@link MongodbQuery}.
|
||||
*
|
||||
* @param query
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applySorting(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Sort sort) {
|
||||
|
||||
// TODO: find better solution than instanceof check
|
||||
if (sort instanceof QSort) {
|
||||
|
||||
List<OrderSpecifier<?>> orderSpecifiers = ((QSort) sort).getOrderSpecifiers();
|
||||
query.orderBy(orderSpecifiers.toArray(new OrderSpecifier<?>[orderSpecifiers.size()]));
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
sort.stream().map(this::toOrder).forEach(it -> query.orderBy(it));
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}.
|
||||
*
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private OrderSpecifier<?> toOrder(Order order) {
|
||||
|
||||
Expression<Object> property = builder.get(order.getProperty());
|
||||
|
||||
return new OrderSpecifier(
|
||||
order.isAscending() ? com.querydsl.core.types.Order.ASC : com.querydsl.core.types.Order.DESC, property);
|
||||
public QuerydslMongoRepository(MongoEntityInformation<T, ?> entityInformation, MongoOperations mongoOperations,
|
||||
EntityPathResolver resolver) {
|
||||
super(entityInformation, mongoOperations, resolver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2017 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.mongodb.repository.custom;
|
||||
|
||||
import org.springframework.data.mongodb.core.User;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ComposedRepository extends Repository<User, String>, RepositoryMixin {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2017 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.mongodb.repository.custom;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for composed Repository implementations.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class ComposedRepositoryImplementationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableMongoRepositories
|
||||
@ImportResource("classpath:infrastructure.xml")
|
||||
static class Config {}
|
||||
|
||||
@Autowired ComposedRepository composedRepository;
|
||||
|
||||
@Test // DATAMONGO-1702
|
||||
public void shouldExecuteMethodOnCustomRepositoryImplementation() {
|
||||
assertThat(composedRepository.getFoo()).isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2017 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.mongodb.repository.custom;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface RepositoryMixin {
|
||||
|
||||
String getFoo();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2017 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.mongodb.repository.custom;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class RepositoryMixinImpl implements RepositoryMixin {
|
||||
|
||||
@Override
|
||||
public String getFoo() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration test for {@link QuerydslMongoRepository}.
|
||||
* Integration test for {@link QuerydslMongoPredicateExecutor}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
@@ -44,10 +44,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration(
|
||||
locations = "/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class QueryDslMongoRepositoryIntegrationTests {
|
||||
public class QuerydslMongoPredicateExecutorIntegrationTests {
|
||||
|
||||
@Autowired MongoOperations operations;
|
||||
QuerydslMongoRepository<Person, String> repository;
|
||||
QuerydslMongoPredicateExecutor<Person> repository;
|
||||
|
||||
Person dave, oliver, carter;
|
||||
QPerson person;
|
||||
@@ -57,7 +57,7 @@ public class QueryDslMongoRepositoryIntegrationTests {
|
||||
|
||||
MongoRepositoryFactory factory = new MongoRepositoryFactory(operations);
|
||||
MongoEntityInformation<Person, String> entityInformation = factory.getEntityInformation(Person.class);
|
||||
repository = new QuerydslMongoRepository<>(entityInformation, operations);
|
||||
repository = new QuerydslMongoPredicateExecutor<Person>(entityInformation, operations);
|
||||
|
||||
operations.dropCollection(Person.class);
|
||||
|
||||
@@ -67,7 +67,7 @@ public class QueryDslMongoRepositoryIntegrationTests {
|
||||
|
||||
person = new QPerson("person");
|
||||
|
||||
repository.saveAll(Arrays.asList(oliver, dave, carter));
|
||||
operations.insertAll(Arrays.asList(oliver, dave, carter));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1146
|
||||
Reference in New Issue
Block a user