DATAMONGO-1738 - Polishing.

Adapt stream execution to changes in fluent API. Use fluent API for GeoNear executions. Remove unused code, update JavaDoc. Remove superfluous exception declaration in tests.

Original pull request: #484.
This commit is contained in:
Mark Paluch
2017-07-18 11:04:31 +02:00
parent dd8fc1a591
commit ada8c4ec8d
6 changed files with 158 additions and 238 deletions

View File

@@ -24,7 +24,6 @@ import org.springframework.data.mongodb.repository.query.MongoQueryExecution.Geo
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.SlicedExecution;
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.StreamExecution;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
@@ -33,7 +32,7 @@ import org.springframework.util.Assert;
/**
* Base class for {@link RepositoryQuery} implementations for Mongo.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
@@ -47,7 +46,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
/**
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
*
*
* @param method must not be {@literal null}.
* @param operations must not be {@literal null}.
*/
@@ -66,7 +65,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
.inCollection(method.getEntityInformation().getCollectionName());
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
*/
@@ -80,8 +79,9 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
*/
public Object execute(Object[] parameters) {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method, parameters);
Query query = createQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));
ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(operations.getConverter(),
new MongoParametersParameterAccessor(method, parameters));
Query query = createQuery(accessor);
applyQueryMetaAttributesWhenPresent(query);
@@ -94,18 +94,18 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
return processor.processResult(execution.execute(query));
}
private MongoQueryExecution getExecution(MongoParameterAccessor accessor, FindOperationWithQuery<?> operation) {
private MongoQueryExecution getExecution(ConvertingParameterAccessor accessor, FindOperationWithQuery<?> operation) {
if (isDeleteQuery()) {
return new DeleteExecution(operations, method);
} else if (method.isGeoNearQuery() && method.isPageQuery()) {
return new PagingGeoNearExecution(operations, method, accessor, this);
return new PagingGeoNearExecution(operation, method, accessor, this);
} else if (method.isGeoNearQuery()) {
return new GeoNearExecution(operations, method, accessor);
return new GeoNearExecution(operation, method, accessor);
} else if (method.isSliceQuery()) {
return new SlicedExecution(operation, accessor.getPageable());
} else if (method.isStreamQuery()) {
return new StreamExecution(operation);
return q -> operation.matching(q).stream();
} else if (method.isCollectionQuery()) {
return q -> operation.matching(q.with(accessor.getPageable())).all();
} else if (method.isPageQuery()) {
@@ -132,7 +132,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
* Creates a {@link Query} instance using the given {@link ConvertingParameterAccessor}. Will delegate to
* {@link #createQuery(ConvertingParameterAccessor)} by default but allows customization of the count query to be
* triggered.
*
*
* @param accessor must not be {@literal null}.
* @return
*/
@@ -142,7 +142,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
/**
* Creates a {@link Query} instance using the given {@link ParameterAccessor}
*
*
* @param accessor must not be {@literal null}.
* @return
*/
@@ -150,7 +150,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
/**
* Returns whether the query should get a count projection applied.
*
*
* @return
*/
protected abstract boolean isCountQuery();
@@ -165,7 +165,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
/**
* Return weather the query should delete matching documents.
*
*
* @return
* @since 1.5
*/

View File

@@ -30,15 +30,12 @@ import org.springframework.data.geo.GeoPage;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
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.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.data.util.CloseableIterator;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation;
import com.mongodb.client.result.DeleteResult;
@@ -52,31 +49,11 @@ import com.mongodb.client.result.DeleteResult;
* @author Mark Paluch
* @author Christoph Strobl
*/
@FunctionalInterface
interface MongoQueryExecution {
Object execute(Query query);
/**
* {@link MongoQueryExecution} for collection returning queries.
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
final class CollectionExecution implements MongoQueryExecution {
private final @NonNull ExecutableFindOperation.FindOperationWithQuery<?> find;
private final @NonNull Pageable pageable;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public Object execute(Query query) {
return find.matching(query.with(pageable)).all();
}
}
/**
* {@link MongoQueryExecution} for {@link Slice} query methods.
*
@@ -85,7 +62,7 @@ interface MongoQueryExecution {
* @since 1.5
*/
@RequiredArgsConstructor
static final class SlicedExecution implements MongoQueryExecution {
final class SlicedExecution implements MongoQueryExecution {
private final @NonNull FindOperationWithQuery<?> find;
private final @NonNull Pageable pageable;
@@ -117,7 +94,7 @@ interface MongoQueryExecution {
* @author Mark Paluch
*/
@RequiredArgsConstructor
static final class PagedExecution implements MongoQueryExecution {
final class PagedExecution implements MongoQueryExecution {
private final @NonNull FindOperationWithQuery<?> operation;
private final @NonNull Pageable pageable;
@@ -149,43 +126,21 @@ interface MongoQueryExecution {
}
}
/**
* {@link MongoQueryExecution} to perform a count projection.
*
* @author Oliver Gierke
* @author Mark Paluch
* @since 1.10
*/
@RequiredArgsConstructor
static final class CountExecution implements MongoQueryExecution {
private final @NonNull FindOperationWithQuery<?> operation;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public Object execute(Query query) {
return operation.count();
}
}
/**
* {@link MongoQueryExecution} to execute geo-near queries.
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
static class GeoNearExecution implements MongoQueryExecution {
class GeoNearExecution implements MongoQueryExecution {
private final MongoOperations operations;
private final MongoQueryMethod method;
private final MongoParameterAccessor accessor;
private final @NonNull FindOperationWithQuery<?> operation;
private final @NonNull MongoQueryMethod method;
private final @NonNull MongoParameterAccessor accessor;
/*
* (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
public Object execute(Query query) {
@@ -195,10 +150,7 @@ interface MongoQueryExecution {
}
@SuppressWarnings("unchecked")
protected GeoResults<Object> doExecuteQuery(Query query) {
Class<?> type = method.getReturnedObjectType();
String collection = method.getEntityInformation().getCollectionName();
GeoResults<Object> doExecuteQuery(Query query) {
Point nearLocation = accessor.getGeoNearLocation();
NearQuery nearQuery = NearQuery.near(nearLocation);
@@ -217,7 +169,7 @@ interface MongoQueryExecution {
nearQuery.with(pageable);
}
return (GeoResults<Object>) operations.geoNear(nearQuery, type, collection);
return (GeoResults<Object>) operation.near(nearQuery).all();
}
private static boolean isListOfGeoResult(TypeInformation<?> returnType) {
@@ -237,48 +189,42 @@ interface MongoQueryExecution {
* @author Oliver Gierke
* @author Mark Paluch
*/
static final class PagingGeoNearExecution extends GeoNearExecution {
final class PagingGeoNearExecution extends GeoNearExecution {
private final MongoOperations operations;
private final MongoQueryMethod method;
private final MongoParameterAccessor accessor;
private final FindOperationWithQuery<?> operation;
private final ConvertingParameterAccessor accessor;
private final AbstractMongoQuery mongoQuery;
public PagingGeoNearExecution(MongoOperations operations, MongoQueryMethod method, MongoParameterAccessor accessor,
AbstractMongoQuery query) {
PagingGeoNearExecution(FindOperationWithQuery<?> operation, MongoQueryMethod method,
ConvertingParameterAccessor accessor, AbstractMongoQuery query) {
super(operations, method, accessor);
super(operation, method, accessor);
this.accessor = accessor;
this.operations = operations;
this.operation = operation;
this.mongoQuery = query;
this.method = method;
}
/*
* (non-Javadoc)
* @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)
*/
@Override
public Object execute(Query query) {
String collectionName = method.getEntityInformation().getCollectionName();
GeoResults<Object> geoResults = doExecuteQuery(query);
Page<GeoResult<Object>> page = PageableExecutionUtils.getPage(geoResults.getContent(), accessor.getPageable(),
() -> {
Query countQuery = mongoQuery
.createCountQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));
Query countQuery = mongoQuery.createCountQuery(accessor);
countQuery = mongoQuery.applyQueryMetaAttributesWhenPresent(countQuery);
return operations.count(countQuery, collectionName);
return operation.matching(countQuery).count();
});
// transform to GeoPage after applying optimization
return new GeoPage<Object>(geoResults, accessor.getPageable(), page.getTotalElements());
return new GeoPage<>(geoResults, accessor.getPageable(), page.getTotalElements());
}
}
@@ -288,10 +234,10 @@ interface MongoQueryExecution {
* @since 1.5
*/
@RequiredArgsConstructor
static final class DeleteExecution implements MongoQueryExecution {
final class DeleteExecution implements MongoQueryExecution {
private final MongoOperations operations;
private final MongoQueryMethod method;
private final @NonNull MongoOperations operations;
private final @NonNull MongoQueryMethod method;
/*
* (non-Javadoc)
@@ -311,27 +257,4 @@ interface MongoQueryExecution {
return writeResult != null ? writeResult.getDeletedCount() : 0L;
}
}
/**
* @author Thomas Darimont
* @since 1.7
*/
@RequiredArgsConstructor
static final class StreamExecution implements MongoQueryExecution {
private final @NonNull FindOperationWithQuery<?> operation;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.MongoQueryExecution#execute(org.springframework.data.mongodb.core.query.Query)
*/
@Override
@SuppressWarnings("unchecked")
public Object execute(Query query) {
TerminatingFindOperation<?> matching = operation.matching(query);
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) matching.stream());
}
}
}

View File

@@ -17,8 +17,8 @@ package org.springframework.data.mongodb.repository.query;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
@@ -57,7 +57,6 @@ import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import com.mongodb.WriteResult;
import com.mongodb.client.result.DeleteResult;
/**
@@ -77,7 +76,6 @@ public class AbstractMongoQueryUnitTests {
@Mock FindOperationWithQuery<?> withQueryMock;
@Mock BasicMongoPersistentEntity<?> persitentEntityMock;
@Mock MongoMappingContext mappingContextMock;
@Mock WriteResult writeResultMock;
@Mock DeleteResult deleteResultMock;
@Before
@@ -100,7 +98,7 @@ public class AbstractMongoQueryUnitTests {
}
@Test // DATAMONGO-566
public void testDeleteExecutionCallsRemoveCorreclty() {
public void testDeleteExecutionCallsRemoveCorrectly() {
createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
@@ -134,7 +132,7 @@ public class AbstractMongoQueryUnitTests {
MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class);
query.setDeleteQuery(true);
assertThat(query.execute(new Object[] { "fake" }), is((Object) 100L));
assertThat(query.execute(new Object[] { "fake" }), is(100L));
verify(mongoOperationsMock, times(1)).remove(any(), eq(Person.class), eq("persons"));
}
@@ -268,7 +266,7 @@ public class AbstractMongoQueryUnitTests {
AbstractMongoQuery query = createQueryForMethod("findByLastname", String.class);
assertThat(query.execute(new Object[] { "lastname" }), is((Object) reference));
assertThat(query.execute(new Object[] { "lastname" }), is(reference));
}
private MongoQueryFake createQueryForMethod(String methodName, Class<?>... paramTypes) {
@@ -282,16 +280,13 @@ public class AbstractMongoQueryUnitTests {
return new MongoQueryFake(queryMethod, mongoOperationsMock);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (SecurityException e) {
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
private static class MongoQueryFake extends AbstractMongoQuery {
private boolean isCountQuery;
private boolean isDeleteQuery;
public MongoQueryFake(MongoQueryMethod method, MongoOperations operations) {
@@ -305,7 +300,7 @@ public class AbstractMongoQueryUnitTests {
@Override
protected boolean isCountQuery() {
return isCountQuery;
return false;
}
@Override

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.mongodb.repository.query;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
@@ -37,6 +37,7 @@ import org.springframework.data.geo.Metrics;
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.TerminatingFindNearOperation;
import org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFindOperation;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
@@ -58,15 +59,17 @@ import org.springframework.util.ReflectionUtils;
* Unit tests for {@link MongoQueryExecution}.
*
* @author Mark Paluch
* @author Oliver Gierke
* @soundtrack U Can't Touch This - MC Hammer
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unchecked")
public class MongoQueryExecutionUnitTests {
@Mock MongoOperations mongoOperationsMock;
@Mock FindOperation<?> findOperationMock;
@Mock FindOperationWithQuery<?> operationMock;
@Mock FindOperation<Object> findOperationMock;
@Mock FindOperationWithQuery<Object> operationMock;
@Mock TerminatingFindOperation<Object> terminatingMock;
@Mock TerminatingFindNearOperation<Object> terminatingGeoMock;
@Mock DbRefResolver dbRefResolver;
Point POINT = new Point(10, 20);
@@ -77,12 +80,13 @@ public class MongoQueryExecutionUnitTests {
Method method = ReflectionUtils.findMethod(PersonRepository.class, "findByLocationNear", Point.class, Distance.class,
Pageable.class);
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
MappingMongoConverter converter;
@Before
public void setUp() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
@SuppressWarnings("unchecked")
public void setUp() {
converter = new MappingMongoConverter(dbRefResolver, context);
when(mongoOperationsMock.getConverter()).thenReturn(converter);
when(mongoOperationsMock.query(any(Class.class))).thenReturn(findOperationMock);
}
@@ -90,83 +94,77 @@ public class MongoQueryExecutionUnitTests {
@Test // DATAMONGO-1464
public void pagedExecutionShouldNotGenerateCountQueryIfQueryReportedNoResults() {
TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
doReturn(terminating).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminating).all();
doReturn(terminatingMock).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminatingMock).all();
PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(0, 10));
execution.execute(new Query());
verify(terminating).all();
verify(terminating, never()).count();
verify(terminatingMock).all();
verify(terminatingMock, never()).count();
}
@Test // DATAMONGO-1464
public void pagedExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() {
TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
doReturn(terminating).when(operationMock).matching(any(Query.class));
doReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person())).when(terminating).all();
doReturn(terminatingMock).when(operationMock).matching(any(Query.class));
doReturn(Arrays.asList(new Person(), new Person(), new Person(), new Person())).when(terminatingMock).all();
PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(0, 10));
execution.execute(new Query());
verify(terminating).all();
verify(terminating, never()).count();
verify(terminatingMock).all();
verify(terminatingMock, never()).count();
}
@Test // DATAMONGO-1464
public void pagedExecutionRetrievesObjectsForPageableOutOfRange() throws Exception {
public void pagedExecutionRetrievesObjectsForPageableOutOfRange() {
TerminatingFindOperation<Object> terminating = mock(TerminatingFindOperation.class);
doReturn(terminating).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminating).all();
doReturn(terminatingMock).when(operationMock).matching(any(Query.class));
doReturn(Collections.emptyList()).when(terminatingMock).all();
PagedExecution execution = new PagedExecution(operationMock, PageRequest.of(2, 10));
execution.execute(new Query());
verify(terminating).all();
verify(terminating).count();
verify(terminatingMock).all();
verify(terminatingMock).count();
}
@Test // DATAMONGO-1464
public void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() throws Exception {
public void pagingGeoExecutionShouldUseCountFromResultWithOffsetAndResultsWithinPageSize() {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
new Object[] { POINT, DISTANCE, PageRequest.of(0, 10) });
GeoResult<Person> result = new GeoResult<>(new Person(), DISTANCE);
when(findOperationMock.near(any(NearQuery.class))).thenReturn(terminatingGeoMock);
doReturn(new GeoResults<>(Arrays.asList(result, result, result, result))).when(terminatingGeoMock).all();
ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(converter,
new MongoParametersParameterAccessor(queryMethod, new Object[] { POINT, DISTANCE, PageRequest.of(0, 10) }));
PartTreeMongoQuery query = new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
GeoResult<Person> result = new GeoResult<Person>(new Person(), DISTANCE);
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Arrays.asList(result, result, result, result)));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, queryMethod, accessor, query);
PagingGeoNearExecution execution = new PagingGeoNearExecution(findOperationMock, queryMethod, accessor, query);
execution.execute(new Query());
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock, never()).count(any(Query.class), eq("person"));
verify(terminatingGeoMock).all();
}
@Test // DATAMONGO-1464
public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() throws Exception {
public void pagingGeoExecutionRetrievesObjectsForPageableOutOfRange() {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
new Object[] { POINT, DISTANCE, PageRequest.of(2, 10) });
when(findOperationMock.near(any(NearQuery.class))).thenReturn(terminatingGeoMock);
doReturn(new GeoResults<>(Collections.emptyList())).when(terminatingGeoMock).all();
doReturn(terminatingMock).when(findOperationMock).matching(any(Query.class));
ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(converter,
new MongoParametersParameterAccessor(queryMethod, new Object[] { POINT, DISTANCE, PageRequest.of(2, 10) }));
PartTreeMongoQuery query = new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
when(mongoOperationsMock.geoNear(any(NearQuery.class), eq(Person.class), eq("person")))
.thenReturn(new GeoResults<Person>(Collections.<GeoResult<Person>> emptyList()));
PagingGeoNearExecution execution = new PagingGeoNearExecution(mongoOperationsMock, queryMethod, accessor, query);
PagingGeoNearExecution execution = new PagingGeoNearExecution(findOperationMock, queryMethod, accessor, query);
execution.execute(new Query());
verify(mongoOperationsMock).geoNear(any(NearQuery.class), eq(Person.class), eq("person"));
verify(mongoOperationsMock).count(any(Query.class), eq("person"));
verify(terminatingGeoMock).all();
verify(terminatingMock).count();
}
interface PersonRepository extends Repository<Person, Long> {

View File

@@ -88,14 +88,13 @@ public class PartTreeMongoQueryUnitTests {
exception.expect(IllegalStateException.class);
exception.expectMessage("findByLastname");
deriveQueryFromMethod("findByLastname", new Object[] { "foo" });
deriveQueryFromMethod("findByLastname", "foo");
}
@Test // DATAMOGO-952
public void singleFieldJsonIncludeRestrictionShouldBeConsidered() {
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstname",
new Object[] { "foo" });
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstname", "foo");
assertThat(query.getFieldsObject(), is(new Document().append("firstname", 1)));
}
@@ -103,8 +102,8 @@ public class PartTreeMongoQueryUnitTests {
@Test // DATAMOGO-952
public void multiFieldJsonIncludeRestrictionShouldBeConsidered() {
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstnameAndLastname",
new Object[] { "foo", "bar" });
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findByFirstnameAndLastname", "foo",
"bar");
assertThat(query.getFieldsObject(), is(new Document().append("firstname", 1).append("lastname", 1)));
}
@@ -113,7 +112,7 @@ public class PartTreeMongoQueryUnitTests {
public void multiFieldJsonExcludeRestrictionShouldBeConsidered() {
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findPersonByFirstnameAndLastname",
new Object[] { "foo", "bar" });
"foo", "bar");
assertThat(query.getFieldsObject(), is(new Document().append("firstname", 0).append("lastname", 0)));
}
@@ -121,8 +120,8 @@ public class PartTreeMongoQueryUnitTests {
@Test // DATAMOGO-973
public void shouldAddFullTextParamCorrectlyToDerivedQuery() {
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findPersonByFirstname",
new Object[] { "text", TextCriteria.forDefaultLanguage().matching("search") });
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findPersonByFirstname", "text",
TextCriteria.forDefaultLanguage().matching("search"));
assertThat(query, isTextQuery().searchingFor("search").where(new Criteria("firstname").is("text")));
}
@@ -131,9 +130,9 @@ public class PartTreeMongoQueryUnitTests {
public void propagatesRootExceptionForInvalidQuery() {
exception.expect(IllegalStateException.class);
exception.expectCause(is(org.hamcrest.Matchers.<Throwable> instanceOf(JSONParseException.class)));
exception.expectCause(is(instanceOf(JSONParseException.class)));
deriveQueryFromMethod("findByAge", new Object[] { 1 });
deriveQueryFromMethod("findByAge", 1);
}
@Test // DATAMONGO-1345, DATAMONGO-1735
@@ -146,8 +145,8 @@ public class PartTreeMongoQueryUnitTests {
Document fieldsObject = deriveQueryFromMethod("findPersonProjectedBy", new Object[0]).getFieldsObject();
assertThat(fieldsObject.get("firstname"), is((Object) 1));
assertThat(fieldsObject.get("lastname"), is((Object) 1));
assertThat(fieldsObject.get("firstname"), is(1));
assertThat(fieldsObject.get("lastname"), is(1));
}
@Test // DATAMONGO-1345
@@ -155,8 +154,8 @@ public class PartTreeMongoQueryUnitTests {
Document fieldsObject = deriveQueryFromMethod("findPersonDtoByAge", new Object[] { 42 }).getFieldsObject();
assertThat(fieldsObject.get("firstname"), is((Object) 1));
assertThat(fieldsObject.get("lastname"), is((Object) 1));
assertThat(fieldsObject.get("firstname"), is(1));
assertThat(fieldsObject.get("lastname"), is(1));
}
@Test // DATAMONGO-1345
@@ -164,9 +163,9 @@ public class PartTreeMongoQueryUnitTests {
Document fields = deriveQueryFromMethod("findDynamicallyProjectedBy", ExtendedProjection.class).getFieldsObject();
assertThat(fields.get("firstname"), is((Object) 1));
assertThat(fields.get("lastname"), is((Object) 1));
assertThat(fields.get("age"), is((Object) 1));
assertThat(fields.get("firstname"), is(1));
assertThat(fields.get("lastname"), is(1));
assertThat(fields.get("age"), is(1));
}
@Test // DATAMONGO-1500
@@ -174,8 +173,8 @@ public class PartTreeMongoQueryUnitTests {
org.springframework.data.mongodb.core.query.Query query = deriveQueryFromMethod("findBySex", Sex.FEMALE);
assertThat(query.getQueryObject().get("sex"), is((Object) Sex.FEMALE));
assertThat(query.getFieldsObject().get("firstname"), is((Object) 1));
assertThat(query.getQueryObject().get("sex"), is(Sex.FEMALE));
assertThat(query.getFieldsObject().get("firstname"), is(1));
}
@Test // DATAMONGO-1729, DATAMONGO-1735
@@ -210,9 +209,7 @@ public class PartTreeMongoQueryUnitTests {
mappingContext);
return new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (SecurityException e) {
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}

View File

@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -83,7 +84,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test
public void bindsSimplePropertyCorrectly() throws Exception {
public void bindsSimplePropertyCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
@@ -95,7 +96,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test
public void bindsComplexPropertyCorrectly() throws Exception {
public void bindsComplexPropertyCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByAddress", Address.class);
@@ -114,7 +115,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test
public void bindsMultipleParametersCorrectly() throws Exception {
public void bindsMultipleParametersCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAndAddress", String.class, Address.class);
@@ -133,7 +134,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test
public void bindsNullParametersCorrectly() throws Exception {
public void bindsNullParametersCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByAddress", Address.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, new Object[] { null });
@@ -144,7 +145,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-821
public void bindsDbrefCorrectly() throws Exception {
public void bindsDbrefCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByHavingSizeFansNotZero");
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter);
@@ -154,19 +155,19 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-566
public void constructsDeleteQueryCorrectly() throws Exception {
public void constructsDeleteQueryCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("removeByLastname", String.class);
assertThat(mongoQuery.isDeleteQuery(), is(true));
}
@Test(expected = IllegalArgumentException.class) // DATAMONGO-566
public void preventsDeleteAndCountFlagAtTheSameTime() throws Exception {
public void preventsDeleteAndCountFlagAtTheSameTime() {
createQueryForMethod("invalidMethod", String.class);
}
@Test // DATAMONGO-420
public void shouldSupportFindByParameterizedCriteriaAndFields() throws Exception {
public void shouldSupportFindByParameterizedCriteriaAndFields() {
ConvertingParameterAccessor accessor = new ConvertingParameterAccessor(converter,
StubParameterAccessor.getAccessor(converter, //
@@ -183,7 +184,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-420
public void shouldSupportRespectExistingQuotingInFindByTitleBeginsWithExplicitQuoting() throws Exception {
public void shouldSupportRespectExistingQuotingInFindByTitleBeginsWithExplicitQuoting() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "fun");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByTitleBeginsWithExplicitQuoting", String.class);
@@ -195,7 +196,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-995, DATAMONGO-420
public void shouldParseQueryWithParametersInExpression() throws Exception {
public void shouldParseQueryWithParametersInExpression() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, 1, 2, 3, 4);
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithParametersInExpression", int.class,
@@ -209,7 +210,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-995, DATAMONGO-420
public void bindsSimplePropertyAlreadyQuotedCorrectly() throws Exception {
public void bindsSimplePropertyAlreadyQuotedCorrectly() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
@@ -221,7 +222,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-995, DATAMONGO-420
public void bindsSimplePropertyAlreadyQuotedWithRegexCorrectly() throws Exception {
public void bindsSimplePropertyAlreadyQuotedWithRegexCorrectly() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
@@ -233,7 +234,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-995, DATAMONGO-420
public void bindsSimplePropertyWithRegexCorrectly() throws Exception {
public void bindsSimplePropertyWithRegexCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
@@ -245,7 +246,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1070
public void parsesDbRefDeclarationsCorrectly() throws Exception {
public void parsesDbRefDeclarationsCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("methodWithManuallyDefinedDbRef", String.class);
ConvertingParameterAccessor parameterAccessor = StubParameterAccessor.getAccessor(converter, "myid");
@@ -257,7 +258,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1072
public void shouldParseJsonKeyReplacementCorrectly() throws Exception {
public void shouldParseJsonKeyReplacementCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("methodWithPlaceholderInKeyOfJsonStructure", String.class,
String.class);
@@ -269,7 +270,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-990
public void shouldSupportExpressionsInCustomQueries() throws Exception {
public void shouldSupportExpressionsInCustomQueries() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpression", String.class);
@@ -281,7 +282,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1244
public void shouldSupportExpressionsInCustomQueriesWithNestedObject() throws Exception {
public void shouldSupportExpressionsInCustomQueriesWithNestedObject() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndNestedObject", boolean.class,
@@ -294,7 +295,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1244
public void shouldSupportExpressionsInCustomQueriesWithMultipleNestedObjects() throws Exception {
public void shouldSupportExpressionsInCustomQueriesWithMultipleNestedObjects() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndMultipleNestedObjects",
@@ -308,10 +309,10 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1290
public void shouldSupportNonQuotedBinaryDataReplacement() throws Exception {
public void shouldSupportNonQuotedBinaryDataReplacement() {
byte[] binaryData = "Matthews".getBytes("UTF-8");
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, binaryData);
byte[] binaryData = "Matthews".getBytes(StandardCharsets.UTF_8);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, (Object) binaryData);
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsBinary", byte[].class);
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
@@ -322,7 +323,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1454
public void shouldSupportExistsProjection() throws Exception {
public void shouldSupportExistsProjection() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("existsByLastname", String.class);
@@ -330,7 +331,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565
public void bindsPropertyReferenceMultipleTimesCorrectly() throws Exception {
public void bindsPropertyReferenceMultipleTimesCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByAgeQuotedAndUnquoted", Integer.TYPE);
@@ -347,7 +348,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565
public void shouldIgnorePlaceholderPatternInReplacementValue() throws Exception {
public void shouldIgnorePlaceholderPatternInReplacementValue() {
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "argWith?1andText",
"nothing-special");
@@ -360,7 +361,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565
public void shouldQuoteStringReplacementCorrectly() throws Exception {
public void shouldQuoteStringReplacementCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews', password: 'foo");
@@ -372,7 +373,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565
public void shouldQuoteStringReplacementContainingQuotesCorrectly() throws Exception {
public void shouldQuoteStringReplacementContainingQuotesCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews\", password: \"foo");
@@ -384,7 +385,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565
public void shouldQuoteStringReplacementWithQuotationsCorrectly() throws Exception {
public void shouldQuoteStringReplacementWithQuotationsCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter,
@@ -395,7 +396,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565, DATAMONGO-1575
public void shouldQuoteComplexQueryStringCorrectly() throws Exception {
public void shouldQuoteComplexQueryStringCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "{ $ne : \"calamity\" }");
@@ -405,7 +406,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1565, DATAMONGO-1575
public void shouldQuotationInQuotedComplexQueryString() throws Exception {
public void shouldQuotationInQuotedComplexQueryString() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter,
@@ -417,7 +418,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1575
public void shouldTakeBsonParameterAsIs() throws Exception {
public void shouldTakeBsonParameterAsIs() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByWithBsonArgument", Document.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter,
@@ -428,7 +429,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1575
public void shouldReplaceParametersInInQuotedExpressionOfNestedQueryOperator() throws Exception {
public void shouldReplaceParametersInInQuotedExpressionOfNestedQueryOperator() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameRegex", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "calamity");
@@ -438,7 +439,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldAllowReuseOfPlaceholderWithinQuery() throws Exception {
public void shouldAllowReuseOfPlaceholderWithinQuery() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByReusingPlaceholdersMultipleTimes", String.class,
String.class);
@@ -450,7 +451,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldAllowReuseOfQuotedPlaceholderWithinQuery() throws Exception {
public void shouldAllowReuseOfQuotedPlaceholderWithinQuery() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByReusingPlaceholdersMultipleTimesWhenQuoted",
String.class, String.class);
@@ -462,7 +463,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldAllowReuseOfQuotedPlaceholderWithinQueryAndIncludeSuffixCorrectly() throws Exception {
public void shouldAllowReuseOfQuotedPlaceholderWithinQueryAndIncludeSuffixCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod(
"findByReusingPlaceholdersMultipleTimesWhenQuotedAndSomeStuffAppended", String.class, String.class);
@@ -474,7 +475,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldAllowQuotedParameterWithSuffixAppended() throws Exception {
public void shouldAllowQuotedParameterWithSuffixAppended() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByWhenQuotedAndSomeStuffAppended", String.class,
String.class);
@@ -485,7 +486,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldCaptureReplacementWithComplexSuffixCorrectly() throws Exception {
public void shouldCaptureReplacementWithComplexSuffixCorrectly() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByMultiRegex", String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "calamity");
@@ -497,7 +498,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1603
public void shouldAllowPlaceholderReuseInQuotedValue() throws Exception {
public void shouldAllowPlaceholderReuseInQuotedValue() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameRegex", String.class, String.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "calamity", "regalia");
@@ -509,7 +510,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1605
public void findUsingSpelShouldRetainParameterType() throws Exception {
public void findUsingSpelShouldRetainParameterType() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByUsingSpel", Object.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, 100.01D);
@@ -519,7 +520,7 @@ public class StringBasedMongoQueryUnitTests {
}
@Test // DATAMONGO-1605
public void findUsingSpelShouldRetainNullValues() throws Exception {
public void findUsingSpelShouldRetainNullValues() {
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByUsingSpel", Object.class);
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, new Object[] { null });
@@ -528,13 +529,19 @@ public class StringBasedMongoQueryUnitTests {
assertThat(query.getQueryObject(), is(new Document("arg0", null)));
}
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) {
Method method = SampleRepository.class.getMethod(name, parameters);
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
factory, converter.getMappingContext());
return new StringBasedMongoQuery(queryMethod, operations, PARSER, DefaultEvaluationContextProvider.INSTANCE);
try {
Method method = SampleRepository.class.getMethod(name, parameters);
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
factory, converter.getMappingContext());
return new StringBasedMongoQuery(queryMethod, operations, PARSER, DefaultEvaluationContextProvider.INSTANCE);
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
private interface SampleRepository extends Repository<Person, Long> {