Browse Source

DATAMONGO-1738 - Move repository query execution to fluent operations API.

We now use the fluent FindOperations API in AbstractMongoQuery and MongoQueryExecution instead of the MongoOperations. This allows us to eagerly resolve some general execution coordinates (which collection to query etc.) and thus simplify the eventual execution.

Got rid of a couple of very simple QueryExecution implementations that can be replace by a simple lambda. Removed the need to read into a partially filled domain object and then map to the projection DTO as we can now tell the operations to read into the DTO directly.

Adapted unit tests.

Original pull request: #484.
pull/484/merge
Oliver Gierke 9 years ago committed by Mark Paluch
parent
commit
dd8fc1a591
  1. 66
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java
  2. 224
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java
  3. 66
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java
  4. 63
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java
  5. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java
  6. 5
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java

66
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java

@ -15,25 +15,20 @@
*/ */
package org.springframework.data.mongodb.repository.query; package org.springframework.data.mongodb.repository.query;
import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithProjection;
import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithQuery;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.CollectionExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.CountExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.ExistsExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.GeoNearExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.GeoNearExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagingGeoNearExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagingGeoNearExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.ResultProcessingConverter;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.ResultProcessingExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SingleEntityExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.StreamExecution; import org.springframework.data.mongodb.repository.query.MongoQueryExecution.StreamExecution;
import org.springframework.data.repository.query.ParameterAccessor; import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor; import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -48,7 +43,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
private final MongoQueryMethod method; private final MongoQueryMethod method;
private final MongoOperations operations; private final MongoOperations operations;
private final EntityInstantiators instantiators; private final FindOperationWithProjection<?> findOperationWithProjection;
/** /**
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}. * Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
@ -63,7 +58,12 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
this.method = method; this.method = method;
this.operations = operations; this.operations = operations;
this.instantiators = new EntityInstantiators();
ReturnedType returnedType = method.getResultProcessor().getReturnedType();
this.findOperationWithProjection = operations//
.query(returnedType.getDomainType())//
.inCollection(method.getEntityInformation().getCollectionName());
} }
/* /*
@ -86,52 +86,36 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
applyQueryMetaAttributesWhenPresent(query); applyQueryMetaAttributesWhenPresent(query);
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor); ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
String collection = method.getEntityInformation().getCollectionName(); ReturnedType returnedType = processor.getReturnedType();
FindOperationWithQuery<?> find = findOperationWithProjection.as(returnedType.getTypeToRead());
MongoQueryExecution execution = getExecution(query, accessor,
new ResultProcessingConverter(processor, operations, instantiators));
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
}
/**
* Returns the execution instance to use.
*
* @param query must not be {@literal null}.
* @param parameters must not be {@literal null}.
* @param accessor must not be {@literal null}.
* @return
*/
private MongoQueryExecution getExecution(Query query, MongoParameterAccessor accessor,
Converter<Object, Object> resultProcessing) {
if (method.isStreamQuery()) { MongoQueryExecution execution = getExecution(accessor, find);
return new StreamExecution(operations, resultProcessing);
}
return new ResultProcessingExecution(getExecutionToWrap(query, accessor), resultProcessing); return processor.processResult(execution.execute(query));
} }
private MongoQueryExecution getExecutionToWrap(Query query, MongoParameterAccessor accessor) { private MongoQueryExecution getExecution(MongoParameterAccessor accessor, FindOperationWithQuery<?> operation) {
if (isDeleteQuery()) { if (isDeleteQuery()) {
return new DeleteExecution(operations, method); return new DeleteExecution(operations, method);
} else if (method.isGeoNearQuery() && method.isPageQuery()) { } else if (method.isGeoNearQuery() && method.isPageQuery()) {
return new PagingGeoNearExecution(operations, accessor, method.getReturnType(), this); return new PagingGeoNearExecution(operations, method, accessor, this);
} else if (method.isGeoNearQuery()) { } else if (method.isGeoNearQuery()) {
return new GeoNearExecution(operations, accessor, method.getReturnType()); return new GeoNearExecution(operations, method, accessor);
} else if (method.isSliceQuery()) { } else if (method.isSliceQuery()) {
return new SlicedExecution(operations, accessor.getPageable()); return new SlicedExecution(operation, accessor.getPageable());
} else if (method.isStreamQuery()) {
return new StreamExecution(operation);
} else if (method.isCollectionQuery()) { } else if (method.isCollectionQuery()) {
return new CollectionExecution(operations, accessor.getPageable()); return q -> operation.matching(q.with(accessor.getPageable())).all();
} else if (method.isPageQuery()) { } else if (method.isPageQuery()) {
return new PagedExecution(operations, accessor.getPageable()); return new PagedExecution(operation, accessor.getPageable());
} else if (isCountQuery()) { } else if (isCountQuery()) {
return new CountExecution(operations); return q -> operation.matching(q).count();
} else if (isExistsQuery()) { } else if (isExistsQuery()) {
return new ExistsExecution(operations); return q -> operation.matching(q).exists();
} else { } else {
return new SingleEntityExecution(operations); return q -> operation.matching(q).oneValue();
} }
} }

224
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java

@ -19,11 +19,7 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Range; import org.springframework.data.domain.Range;
@ -34,16 +30,16 @@ import org.springframework.data.geo.GeoPage;
import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point; import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.ExecutableFindOperation;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithQuery;
import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFindOperation;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.ReturnedType;
import org.springframework.data.repository.support.PageableExecutionUtils; import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.data.util.CloseableIterator; import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.StreamUtils; import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation; import org.springframework.data.util.TypeInformation;
import org.springframework.util.ClassUtils;
import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.DeleteResult;
@ -58,7 +54,7 @@ import com.mongodb.client.result.DeleteResult;
*/ */
interface MongoQueryExecution { interface MongoQueryExecution {
Object execute(Query query, Class<?> type, String collection); Object execute(Query query);
/** /**
* {@link MongoQueryExecution} for collection returning queries. * {@link MongoQueryExecution} for collection returning queries.
@ -68,16 +64,16 @@ interface MongoQueryExecution {
@RequiredArgsConstructor @RequiredArgsConstructor
final class CollectionExecution implements MongoQueryExecution { final class CollectionExecution implements MongoQueryExecution {
private final @NonNull MongoOperations operations; private final @NonNull ExecutableFindOperation.FindOperationWithQuery<?> find;
private final Pageable pageable; private final @NonNull Pageable pageable;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
return operations.find(query.with(pageable), type, collection); return find.matching(query.with(pageable)).all();
} }
} }
@ -89,24 +85,24 @@ interface MongoQueryExecution {
* @since 1.5 * @since 1.5
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
final class SlicedExecution implements MongoQueryExecution { static final class SlicedExecution implements MongoQueryExecution {
private final @NonNull MongoOperations operations; private final @NonNull FindOperationWithQuery<?> find;
private final @NonNull Pageable pageable; private final @NonNull Pageable pageable;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
int pageSize = pageable.getPageSize(); int pageSize = pageable.getPageSize();
// Apply Pageable but tweak limit to peek into next page // Apply Pageable but tweak limit to peek into next page
Query modifiedQuery = query.with(pageable).limit(pageSize + 1); Query modifiedQuery = query.with(pageable).limit(pageSize + 1);
List result = operations.find(modifiedQuery, type, collection); List result = find.matching(modifiedQuery).all();
boolean hasNext = result.size() > pageSize; boolean hasNext = result.size() > pageSize;
@ -121,19 +117,21 @@ interface MongoQueryExecution {
* @author Mark Paluch * @author Mark Paluch
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
final class PagedExecution implements MongoQueryExecution { static final class PagedExecution implements MongoQueryExecution {
private final @NonNull MongoOperations operations; private final @NonNull FindOperationWithQuery<?> operation;
private final @NonNull Pageable pageable; private final @NonNull Pageable pageable;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
public Object execute(final Query query, final Class<?> type, final String collection) { public Object execute(Query query) {
int overallLimit = query.getLimit();
final int overallLimit = query.getLimit(); TerminatingFindOperation<?> matching = operation.matching(query);
// Apply raw pagination // Apply raw pagination
query.with(pageable); query.with(pageable);
@ -143,35 +141,14 @@ interface MongoQueryExecution {
query.limit((int) (overallLimit - pageable.getOffset())); query.limit((int) (overallLimit - pageable.getOffset()));
} }
return PageableExecutionUtils.getPage(operations.find(query, type, collection), pageable, () -> { return PageableExecutionUtils.getPage(matching.all(), pageable, () -> {
long count = operations.count(query, type, collection); long count = matching.count();
return overallLimit != 0 ? Math.min(count, overallLimit) : count; return overallLimit != 0 ? Math.min(count, overallLimit) : count;
}); });
} }
} }
/**
* {@link MongoQueryExecution} to return a single entity.
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
final class SingleEntityExecution implements MongoQueryExecution {
private final MongoOperations operations;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@Override
public Object execute(Query query, Class<?> type, String collection) {
return operations.findOne(query, type, collection);
}
}
/** /**
* {@link MongoQueryExecution} to perform a count projection. * {@link MongoQueryExecution} to perform a count projection.
* *
@ -182,36 +159,15 @@ interface MongoQueryExecution {
@RequiredArgsConstructor @RequiredArgsConstructor
static final class CountExecution implements MongoQueryExecution { static final class CountExecution implements MongoQueryExecution {
private final MongoOperations operations; private final @NonNull FindOperationWithQuery<?> operation;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
return operations.count(query, type, collection); return operation.count();
}
}
/**
* {@link MongoQueryExecution} to perform an exists projection.
*
* @author Mark Paluch
* @since 1.10
*/
@RequiredArgsConstructor
static final class ExistsExecution implements MongoQueryExecution {
private final MongoOperations operations;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@Override
public Object execute(Query query, Class<?> type, String collection) {
return operations.exists(query, type, collection);
} }
} }
@ -221,25 +177,28 @@ interface MongoQueryExecution {
* @author Oliver Gierke * @author Oliver Gierke
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
class GeoNearExecution implements MongoQueryExecution { static class GeoNearExecution implements MongoQueryExecution {
private final MongoOperations operations; private final MongoOperations operations;
private final MongoQueryMethod method;
private final MongoParameterAccessor accessor; private final MongoParameterAccessor accessor;
private final TypeInformation<?> returnType;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/ */
@Override @Override
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
GeoResults<?> results = doExecuteQuery(query, type, collection); GeoResults<?> results = doExecuteQuery(query);
return isListOfGeoResult() ? results.getContent() : results; return isListOfGeoResult(method.getReturnType()) ? results.getContent() : results;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected GeoResults<Object> doExecuteQuery(Query query, Class<?> type, String collection) { protected GeoResults<Object> doExecuteQuery(Query query) {
Class<?> type = method.getReturnedObjectType();
String collection = method.getEntityInformation().getCollectionName();
Point nearLocation = accessor.getGeoNearLocation(); Point nearLocation = accessor.getGeoNearLocation();
NearQuery nearQuery = NearQuery.near(nearLocation); NearQuery nearQuery = NearQuery.near(nearLocation);
@ -261,7 +220,7 @@ interface MongoQueryExecution {
return (GeoResults<Object>) operations.geoNear(nearQuery, type, collection); return (GeoResults<Object>) operations.geoNear(nearQuery, type, collection);
} }
private boolean isListOfGeoResult() { private static boolean isListOfGeoResult(TypeInformation<?> returnType) {
if (!returnType.getType().equals(List.class)) { if (!returnType.getType().equals(List.class)) {
return false; return false;
@ -278,20 +237,22 @@ interface MongoQueryExecution {
* @author Oliver Gierke * @author Oliver Gierke
* @author Mark Paluch * @author Mark Paluch
*/ */
final class PagingGeoNearExecution extends GeoNearExecution { static final class PagingGeoNearExecution extends GeoNearExecution {
private final MongoOperations operations; private final MongoOperations operations;
private final MongoQueryMethod method;
private final MongoParameterAccessor accessor; private final MongoParameterAccessor accessor;
private final AbstractMongoQuery mongoQuery; private final AbstractMongoQuery mongoQuery;
public PagingGeoNearExecution(MongoOperations operations, MongoParameterAccessor accessor, public PagingGeoNearExecution(MongoOperations operations, MongoQueryMethod method, MongoParameterAccessor accessor,
TypeInformation<?> returnType, AbstractMongoQuery query) { AbstractMongoQuery query) {
super(operations, accessor, returnType); super(operations, method, accessor);
this.accessor = accessor; this.accessor = accessor;
this.operations = operations; this.operations = operations;
this.mongoQuery = query; this.mongoQuery = query;
this.method = method;
} }
/* /*
@ -299,19 +260,20 @@ interface MongoQueryExecution {
* @see org.springframework.data.mongodb.repository.query.MongoQueryExecution.GeoNearExecution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution.GeoNearExecution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/ */
@Override @Override
public Object execute(Query query, Class<?> type, final String collection) { public Object execute(Query query) {
String collectionName = method.getEntityInformation().getCollectionName();
GeoResults<Object> geoResults = doExecuteQuery(query, type, collection); GeoResults<Object> geoResults = doExecuteQuery(query);
Page<GeoResult<Object>> page = PageableExecutionUtils.getPage(geoResults.getContent(), accessor.getPageable(), Page<GeoResult<Object>> page = PageableExecutionUtils.getPage(geoResults.getContent(), accessor.getPageable(),
() -> { () -> {
ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(),
accessor);
Query countQuery = mongoQuery Query countQuery = mongoQuery
.applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor)); .createCountQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));
countQuery = mongoQuery.applyQueryMetaAttributesWhenPresent(countQuery);
return operations.count(countQuery, collection); return operations.count(countQuery, collectionName);
}); });
@ -326,23 +288,26 @@ interface MongoQueryExecution {
* @since 1.5 * @since 1.5
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
final class DeleteExecution implements MongoQueryExecution { static final class DeleteExecution implements MongoQueryExecution {
private final MongoOperations operations; private final MongoOperations operations;
private final MongoQueryMethod method; private final MongoQueryMethod method;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
String collectionName = method.getEntityInformation().getCollectionName();
Class<?> type = method.getEntityInformation().getJavaType();
if (method.isCollectionQuery()) { if (method.isCollectionQuery()) {
return operations.findAllAndRemove(query, type, collection); return operations.findAllAndRemove(query, type, collectionName);
} }
DeleteResult writeResult = operations.remove(query, type, collection); DeleteResult writeResult = operations.remove(query, type, collectionName);
return writeResult != null ? writeResult.getDeletedCount() : 0L; return writeResult != null ? writeResult.getDeletedCount() : 0L;
} }
} }
@ -352,82 +317,21 @@ interface MongoQueryExecution {
* @since 1.7 * @since 1.7
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
final class StreamExecution implements MongoQueryExecution { static final class StreamExecution implements MongoQueryExecution {
private final @NonNull MongoOperations operations; private final @NonNull FindOperationWithQuery<?> operation;
private final @NonNull Converter<Object, Object> resultProcessing;
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/ */
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Object execute(Query query, Class<?> type, String collection) { public Object execute(Query query) {
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) operations.stream(query, type))
.map(new Function<Object, Object>() {
@Override
public Object apply(Object t) {
return resultProcessing.convert(t);
}
});
}
}
/**
* An {@link MongoQueryExecution} that wraps the results of the given delegate with the given result processing.
*
* @author Oliver Gierke
* @since 1.9
*/
@RequiredArgsConstructor
final class ResultProcessingExecution implements MongoQueryExecution {
private final @NonNull MongoQueryExecution delegate;
private final @NonNull Converter<Object, Object> converter;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/
@Override
public Object execute(Query query, Class<?> type, String collection) {
return converter.convert(delegate.execute(query, type, collection));
}
}
/**
* A {@link Converter} to post-process all source objects using the given {@link ResultProcessor}.
*
* @author Oliver Gierke
* @since 1.9
*/
@RequiredArgsConstructor
final class ResultProcessingConverter implements Converter<Object, Object> {
private final @NonNull ResultProcessor processor;
private final @NonNull MongoOperations operations;
private final @NonNull EntityInstantiators instantiators;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Object convert(Object source) {
ReturnedType returnedType = processor.getReturnedType();
if (ClassUtils.isPrimitiveOrWrapper(returnedType.getReturnedType())) {
return source;
}
Converter<Object, Object> converter = new DtoInstantiatingConverter(returnedType.getReturnedType(), TerminatingFindOperation<?> matching = operation.matching(query);
operations.getConverter().getMappingContext(), instantiators);
return processor.processResult(source, converter); return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) matching.stream());
} }
} }
} }

66
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java

@ -17,6 +17,8 @@ package org.springframework.data.mongodb.repository.query;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -24,12 +26,10 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.bson.Document; import org.bson.Document;
import org.hamcrest.core.Is;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
@ -39,6 +39,9 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperation;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithProjection;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithQuery;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.Person;
import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DbRefResolver;
@ -69,6 +72,9 @@ import com.mongodb.client.result.DeleteResult;
public class AbstractMongoQueryUnitTests { public class AbstractMongoQueryUnitTests {
@Mock MongoOperations mongoOperationsMock; @Mock MongoOperations mongoOperationsMock;
@Mock FindOperation<?> findOperationMock;
@Mock FindOperationWithProjection<?> withProjectionMock;
@Mock FindOperationWithQuery<?> withQueryMock;
@Mock BasicMongoPersistentEntity<?> persitentEntityMock; @Mock BasicMongoPersistentEntity<?> persitentEntityMock;
@Mock MongoMappingContext mappingContextMock; @Mock MongoMappingContext mappingContextMock;
@Mock WriteResult writeResultMock; @Mock WriteResult writeResultMock;
@ -87,26 +93,27 @@ public class AbstractMongoQueryUnitTests {
converter.afterPropertiesSet(); converter.afterPropertiesSet();
doReturn(converter).when(mongoOperationsMock).getConverter(); doReturn(converter).when(mongoOperationsMock).getConverter();
doReturn(findOperationMock).when(mongoOperationsMock).query(any());
doReturn(withProjectionMock).when(findOperationMock).inCollection(any());
doReturn(withQueryMock).when(withProjectionMock).as(any());
doReturn(withQueryMock).when(withQueryMock).matching(any());
} }
@SuppressWarnings("unchecked")
@Test // DATAMONGO-566 @Test // DATAMONGO-566
public void testDeleteExecutionCallsRemoveCorreclty() { public void testDeleteExecutionCallsRemoveCorreclty() {
createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" }); createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
verify(mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons")); verify(mongoOperationsMock, times(1)).remove(any(), eq(Person.class), eq("persons"));
verify(mongoOperationsMock, times(0)).find(Matchers.any(Query.class), Matchers.any(Class.class), verify(mongoOperationsMock, times(0)).find(any(), any(), any());
Matchers.anyString());
} }
@SuppressWarnings("unchecked")
@Test // DATAMONGO-566, DATAMONGO-1040 @Test // DATAMONGO-566, DATAMONGO-1040
public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollectionLike() { public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollectionLike() {
createQueryForMethod("deleteByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" }); createQueryForMethod("deleteByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
verify(mongoOperationsMock, times(1)).findAllAndRemove(Mockito.any(Query.class), eq(Person.class), eq("persons")); verify(mongoOperationsMock, times(1)).findAllAndRemove(any(), eq(Person.class), eq("persons"));
} }
@Test // DATAMONGO-566 @Test // DATAMONGO-566
@ -115,21 +122,20 @@ public class AbstractMongoQueryUnitTests {
MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class); MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class);
query.setDeleteQuery(true); query.setDeleteQuery(true);
assertThat(query.execute(new Object[] { "fake" }), Is.<Object> is(0L)); assertThat(query.execute(new Object[] { "fake" }), is(0L));
} }
@Test // DATAMONGO-566, DATAMONGO-978 @Test // DATAMONGO-566, DATAMONGO-978
public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() { public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() {
when(deleteResultMock.getDeletedCount()).thenReturn(100L); when(deleteResultMock.getDeletedCount()).thenReturn(100L);
when(mongoOperationsMock.remove(Matchers.any(Query.class), eq(Person.class), eq("persons"))) when(mongoOperationsMock.remove(any(), eq(Person.class), eq("persons"))).thenReturn(deleteResultMock);
.thenReturn(deleteResultMock);
MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class); MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class);
query.setDeleteQuery(true); query.setDeleteQuery(true);
assertThat(query.execute(new Object[] { "fake" }), is((Object) 100L)); assertThat(query.execute(new Object[] { "fake" }), is((Object) 100L));
verify(mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons")); verify(mongoOperationsMock, times(1)).remove(any(), eq(Person.class), eq("persons"));
} }
@Test // DATAMONGO-957 @Test // DATAMONGO-957
@ -140,7 +146,9 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock).as(Person.class);
verify(withQueryMock).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getValue().getMeta().getComment(), nullValue()); assertThat(captor.getValue().getMeta().getComment(), nullValue());
} }
@ -153,7 +161,10 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock).as(Person.class);
verify(withQueryMock).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getValue().getMeta().getComment(), is("comment")); assertThat(captor.getValue().getMeta().getComment(), is("comment"));
} }
@ -165,7 +176,10 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(mongoOperationsMock, times(1)).count(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock).as(Person.class);
verify(withQueryMock).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getValue().getMeta().getComment(), is("comment")); assertThat(captor.getValue().getMeta().getComment(), is("comment"));
} }
@ -177,7 +191,10 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock).as(Person.class);
verify(withQueryMock).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getValue().getMeta().getComment(), is("comment")); assertThat(captor.getValue().getMeta().getComment(), is("comment"));
} }
@ -193,7 +210,9 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock, times(2)).as(Person.class);
verify(withQueryMock, times(2)).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getAllValues().get(0).getSkip(), is(0L)); assertThat(captor.getAllValues().get(0).getSkip(), is(0L));
assertThat(captor.getAllValues().get(1).getSkip(), is(10L)); assertThat(captor.getAllValues().get(1).getSkip(), is(10L));
@ -211,7 +230,9 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock, times(2)).as(Person.class);
verify(withQueryMock, times(2)).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
assertThat(captor.getAllValues().get(0).getLimit(), is(11)); assertThat(captor.getAllValues().get(0).getLimit(), is(11));
assertThat(captor.getAllValues().get(1).getLimit(), is(11)); assertThat(captor.getAllValues().get(1).getLimit(), is(11));
@ -229,7 +250,9 @@ public class AbstractMongoQueryUnitTests {
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class); ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons")); verify(withProjectionMock, times(2)).as(Person.class);
verify(withQueryMock, times(2)).matching(captor.capture());
verify(findOperationMock).inCollection("persons");
Document expectedSortObject = new Document().append("bar", -1); Document expectedSortObject = new Document().append("bar", -1);
assertThat(captor.getAllValues().get(0).getSortObject(), is(expectedSortObject)); assertThat(captor.getAllValues().get(0).getSortObject(), is(expectedSortObject));
@ -240,8 +263,8 @@ public class AbstractMongoQueryUnitTests {
public void doesNotTryToPostProcessQueryResultIntoWrapperType() { public void doesNotTryToPostProcessQueryResultIntoWrapperType() {
Person reference = new Person(); Person reference = new Person();
when(mongoOperationsMock.findOne(Mockito.any(Query.class), eq(Person.class), eq("persons"))).//
thenReturn(reference); doReturn(reference).when(withQueryMock).oneValue();
AbstractMongoQuery query = createQueryForMethod("findByLastname", String.class); AbstractMongoQuery query = createQueryForMethod("findByLastname", String.class);
@ -269,7 +292,6 @@ public class AbstractMongoQueryUnitTests {
private static class MongoQueryFake extends AbstractMongoQuery { private static class MongoQueryFake extends AbstractMongoQuery {
private boolean isCountQuery; private boolean isCountQuery;
private boolean isExistsQuery;
private boolean isDeleteQuery; private boolean isDeleteQuery;
public MongoQueryFake(MongoQueryMethod method, MongoOperations operations) { public MongoQueryFake(MongoQueryMethod method, MongoOperations operations) {

63
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryExecutionUnitTests.java

@ -15,8 +15,7 @@
*/ */
package org.springframework.data.mongodb.repository.query; package org.springframework.data.mongodb.repository.query;
import static org.mockito.Matchers.any; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -36,6 +35,9 @@ import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point; import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperation;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperationWithQuery;
import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFindOperation;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@ -50,7 +52,6 @@ import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@ -64,6 +65,8 @@ import org.springframework.util.ReflectionUtils;
public class MongoQueryExecutionUnitTests { public class MongoQueryExecutionUnitTests {
@Mock MongoOperations mongoOperationsMock; @Mock MongoOperations mongoOperationsMock;
@Mock FindOperation<?> findOperationMock;
@Mock FindOperationWithQuery<?> operationMock;
@Mock DbRefResolver dbRefResolver; @Mock DbRefResolver dbRefResolver;
Point POINT = new Point(10, 20); Point POINT = new Point(10, 20);
@ -79,46 +82,54 @@ public class MongoQueryExecutionUnitTests {
public void setUp() throws Exception { public void setUp() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context); MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
when(mongoOperationsMock.getConverter()).thenReturn(converter); when(mongoOperationsMock.getConverter()).thenReturn(converter);
when(mongoOperationsMock.query(any(Class.class))).thenReturn(findOperationMock);
} }
@Test // DATAMONGO-1464 @Test // DATAMONGO-1464
public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() { public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person"))) TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
.thenReturn(Collections.<Person> emptyList());
doReturn(terminating).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminating).all();
PagedExecution execution = new PagedExecution(mongoOperationsMock, PageRequest.of(0, 10)); PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(0, 10));
execution.execute(new Query(), Person.class, "person"); execution.execute(new Query());
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person")); verify(terminating).all();
verify(mongoOperationsMock, never()).count(any(Query.class), eq(Person.class), eq("person")); verify(terminating, never()).count();
} }
@Test // DATAMONGO-1464 @Test // DATAMONGO-1464
public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() { public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person"))) TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
.thenReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person()));
PagedExecution execution = new PagedExecution(mongoOperationsMock, PageRequest.of(0, 10)); doReturn(terminating).when(operationMock).matching(any(Query.class));
execution.execute(new Query(), Person.class, "person"); doReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person())).when(terminating).all();
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person")); PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(0, 10));
verify(mongoOperationsMock, never()).count(any(Query.class), eq(Person.class), eq("person")); execution.execute(new Query());
verify(terminating).all();
verify(terminating, never()).count();
} }
@Test // DATAMONGO-1464 @Test // DATAMONGO-1464
public void pagedExecutionRetrievesObjectsForPageableOutOfRange() throws Exception { public void pagedExecutionRetrievesObjectsForPageableOutOfRange() throws Exception {
when(mongoOperationsMock.find(any(Query.class), eq(Person.class), eq("person"))) TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
.thenReturn(Collections.<Person> emptyList());
doReturn(terminating).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminating).all();
PagedExecution execution = new PagedExecution(mongoOperationsMock, PageRequest.of(2, 10)); PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(2, 10));
execution.execute(new Query(), Person.class, "person"); execution.execute(new Query());
verify(mongoOperationsMock).find(any(Query.class), eq(Person.class), eq("person")); verify(terminating).all();
verify(mongoOperationsMock).count(any(Query.class), eq(Person.class), eq("person")); verify(terminating).count();
} }
@Test // DATAMONGO-1464 @Test // DATAMONGO-1464
@ -133,9 +144,8 @@ public class MongoQueryExecutionUnitTests {
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person"))) when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Arrays.asList(result, result, result, result))); .thenReturn(new GeoResults<Person>(Arrays.asList(result, result, result, result)));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, accessor, PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, queryMethod, accessor, query);
ClassTypeInformation.fromReturnTypeOf(method), query); execution.execute(new Query());
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person")); verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock, never()).count(any(Query.class), eq("person")); verify(mongoOperationsMock, never()).count(any(Query.class), eq("person"));
@ -152,9 +162,8 @@ public class MongoQueryExecutionUnitTests {
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person"))) when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Collections.<GeoResult<Person>> emptyList())); .thenReturn(new GeoResults<Person>(Collections.<GeoResult<Person>> emptyList()));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, accessor, PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, queryMethod, accessor, query);
ClassTypeInformation.fromReturnTypeOf(method), query); execution.execute(new Query());
execution.execute(new Query(), Person.class, "person");
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person")); verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock).count(any(Query.class), eq("person")); verify(mongoOperationsMock).count(any(Query.class), eq("person"));

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQueryUnitTests.java

@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.query;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.query.IsTextQuery.*; import static org.springframework.data.mongodb.core.query.IsTextQuery.*;
@ -33,6 +34,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperation;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
@ -63,6 +65,7 @@ import com.mongodb.util.JSONParseException;
public class PartTreeMongoQueryUnitTests { public class PartTreeMongoQueryUnitTests {
@Mock MongoOperations mongoOperationsMock; @Mock MongoOperations mongoOperationsMock;
@Mock FindOperation<?> findOperationMock;
MongoMappingContext mappingContext; MongoMappingContext mappingContext;
@ -75,7 +78,8 @@ public class PartTreeMongoQueryUnitTests {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class)); DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class));
MongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); MongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
when(mongoOperationsMock.getConverter()).thenReturn(converter); doReturn(converter).when(mongoOperationsMock).getConverter();
doReturn(findOperationMock).when(mongoOperationsMock).query(any());
} }
@Test // DATAMOGO-952 @Test // DATAMOGO-952

5
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java

@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.query;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -36,6 +37,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.DocumentTestUtils;
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindOperation;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper; import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
@ -67,6 +69,7 @@ public class StringBasedMongoQueryUnitTests {
SpelExpressionParser PARSER = new SpelExpressionParser(); SpelExpressionParser PARSER = new SpelExpressionParser();
@Mock MongoOperations operations; @Mock MongoOperations operations;
@Mock FindOperation<Object> findOperation;
@Mock DbRefResolver factory; @Mock DbRefResolver factory;
MongoConverter converter; MongoConverter converter;
@ -75,6 +78,8 @@ public class StringBasedMongoQueryUnitTests {
public void setUp() { public void setUp() {
this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); this.converter = new MappingMongoConverter(factory, new MongoMappingContext());
doReturn(findOperation).when(operations).query(any());
} }
@Test @Test

Loading…
Cancel
Save