DATAMONGO-1245 - Initial documentation for Query by Example.
Adopt changes from query by example API refactoring. Related tickets: DATACMNS-810. Original pull request: #341.
This commit is contained in:
committed by
Oliver Gierke
parent
693f5ddf6e
commit
5a78d99af0
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,7 +51,6 @@ import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
@@ -139,7 +138,6 @@ import com.mongodb.util.JSONParseException;
|
||||
* @author Chuong Ngo
|
||||
* @author Christoph Strobl
|
||||
* @author Doménique Tilleuil
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
@@ -341,8 +339,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCursor cursor = collection.find(mappedQuery, mappedFields);
|
||||
QueryCursorPreparer cursorPreparer = new QueryCursorPreparer(query, entityType);
|
||||
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType, collection
|
||||
.getName());
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType,
|
||||
collection.getName());
|
||||
|
||||
return new CloseableIterableCursorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
}
|
||||
@@ -375,8 +373,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
@Deprecated
|
||||
public CommandResult executeCommand(final DBObject command, final int options) {
|
||||
return executeCommand(command, (options & Bytes.QUERYOPTION_SLAVEOK) != 0 ? ReadPreference.secondaryPreferred()
|
||||
: ReadPreference.primary());
|
||||
return executeCommand(command,
|
||||
(options & Bytes.QUERYOPTION_SLAVEOK) != 0 ? ReadPreference.secondaryPreferred() : ReadPreference.primary());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -422,7 +420,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply
|
||||
* limits, skips and so on).
|
||||
*/
|
||||
protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer) {
|
||||
protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch,
|
||||
CursorPreparer preparer) {
|
||||
|
||||
Assert.notNull(query);
|
||||
|
||||
@@ -637,15 +636,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.MongoOperations#findByExample(java.lang.Object)
|
||||
*/
|
||||
public <S extends T, T> List<T> findByExample(S sample) {
|
||||
return findByExample(new Example<S>(sample));
|
||||
return findByExample(Example.of(sample));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.MongoOperations#findByExample(org.springframework.data.domain.Example)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends T, T> List<T> findByExample(Example<S> sample) {
|
||||
|
||||
Assert.notNull(sample, "Sample object must not be null!");
|
||||
return (List<T>) find(new Query(new Criteria().alike(sample)), sample.getSampleType());
|
||||
return (List<T>) find(new Query(new Criteria().alike(sample)), sample.getResultType());
|
||||
}
|
||||
|
||||
public <T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass) {
|
||||
@@ -683,8 +690,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
List<Object> results = (List<Object>) commandResult.get("results");
|
||||
results = results == null ? Collections.emptyList() : results;
|
||||
|
||||
DbObjectCallback<GeoResult<T>> callback = new GeoNearResultDbObjectCallback<T>(new ReadDbObjectCallback<T>(
|
||||
mongoConverter, entityClass, collectionName), near.getMetric());
|
||||
DbObjectCallback<GeoResult<T>> callback = new GeoNearResultDbObjectCallback<T>(
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName), near.getMetric());
|
||||
List<GeoResult<T>> result = new ArrayList<GeoResult<T>>(results.size());
|
||||
|
||||
int index = 0;
|
||||
@@ -760,8 +767,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
public long count(Query query, Class<?> entityClass, String collectionName) {
|
||||
|
||||
Assert.hasText(collectionName);
|
||||
final DBObject dbObject = query == null ? null : queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
final DBObject dbObject = query == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
|
||||
return execute(collectionName, new CollectionCallback<Long>() {
|
||||
public Long doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
@@ -1040,8 +1048,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName,
|
||||
entityClass, dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDoc) : collection.insert(dbDoc,
|
||||
writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDoc)
|
||||
: collection.insert(dbDoc, writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.INSERT);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
@@ -1062,8 +1070,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT_LIST, collectionName, null,
|
||||
null, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDocList) : collection.insert(
|
||||
dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDocList)
|
||||
: collection.insert(dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, null, MongoActionOperation.INSERT_LIST);
|
||||
return null;
|
||||
}
|
||||
@@ -1093,8 +1101,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass,
|
||||
dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.save(dbDoc) : collection.save(dbDoc,
|
||||
writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.save(dbDoc)
|
||||
: collection.save(dbDoc, writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.SAVE);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
@@ -1147,10 +1155,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
DBObject queryObj = query == null ? new BasicDBObject() : queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entity);
|
||||
DBObject updateObj = update == null ? new BasicDBObject() : updateMapper.getMappedObject(
|
||||
update.getUpdateObject(), entity);
|
||||
DBObject queryObj = query == null ? new BasicDBObject()
|
||||
: queryMapper.getMappedObject(query.getQueryObject(), entity);
|
||||
DBObject updateObj = update == null ? new BasicDBObject()
|
||||
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Calling update using query: {} and update: {} in collection: {}",
|
||||
@@ -1291,9 +1299,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
Object idValue = persistentEntity.getPropertyAccessor(entity).getProperty(idProperty);
|
||||
|
||||
if (idValue == null && !MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(idProperty.getType())) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"Cannot autogenerate id of type %s for entity of type %s!", idProperty.getType().getName(), entity.getClass()
|
||||
.getName()));
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!", idProperty.getType().getName(),
|
||||
entity.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1332,12 +1340,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.", new Object[] { serializeToJsonSafely(dboq),
|
||||
collection.getName() });
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.",
|
||||
new Object[] { serializeToJsonSafely(dboq), collection.getName() });
|
||||
}
|
||||
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq) : collection.remove(dboq,
|
||||
writeConcernToUse);
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq)
|
||||
: collection.remove(dboq, writeConcernToUse);
|
||||
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
|
||||
@@ -1353,8 +1361,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass, String collectionName) {
|
||||
return executeFindMultiInternal(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass, collectionName), collectionName);
|
||||
return executeFindMultiInternal(new FindCallback(null), null,
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
@@ -1370,8 +1378,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction,
|
||||
String reduceFunction, Class<T> entityClass) {
|
||||
return mapReduce(query, inputCollectionName, mapFunction, reduceFunction,
|
||||
new MapReduceOptions().outputTypeInline(), entityClass);
|
||||
return mapReduce(query, inputCollectionName, mapFunction, reduceFunction, new MapReduceOptions().outputTypeInline(),
|
||||
entityClass);
|
||||
}
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction,
|
||||
@@ -1382,8 +1390,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection inputCollection = getCollection(inputCollectionName);
|
||||
|
||||
MapReduceCommand command = new MapReduceCommand(inputCollection, mapFunc, reduceFunc,
|
||||
mapReduceOptions.getOutputCollection(), mapReduceOptions.getOutputType(), query == null
|
||||
|| query.getQueryObject() == null ? null : queryMapper.getMappedObject(query.getQueryObject(), null));
|
||||
mapReduceOptions.getOutputCollection(), mapReduceOptions.getOutputType(),
|
||||
query == null || query.getQueryObject() == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(), null));
|
||||
|
||||
copyMapReduceOptionsToCommand(query, mapReduceOptions, command);
|
||||
|
||||
@@ -1719,8 +1728,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
mappedFields, entityClass, collectionName);
|
||||
}
|
||||
|
||||
return executeFindOneInternal(new FindOneCallback(mappedQuery, mappedFields), new ReadDbObjectCallback<T>(
|
||||
this.mongoConverter, entityClass, collectionName), collectionName);
|
||||
return executeFindOneInternal(new FindOneCallback(mappedQuery, mappedFields),
|
||||
new ReadDbObjectCallback<T>(this.mongoConverter, entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1734,8 +1743,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @return the List of converted objects.
|
||||
*/
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass) {
|
||||
return doFind(collectionName, query, fields, entityClass, null, new ReadDbObjectCallback<T>(this.mongoConverter,
|
||||
entityClass, collectionName));
|
||||
return doFind(collectionName, query, fields, entityClass, null,
|
||||
new ReadDbObjectCallback<T>(this.mongoConverter, entityClass, collectionName));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1753,8 +1762,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass,
|
||||
CursorPreparer preparer) {
|
||||
return doFind(collectionName, query, fields, entityClass, preparer, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass, collectionName));
|
||||
return doFind(collectionName, query, fields, entityClass, preparer,
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName));
|
||||
}
|
||||
|
||||
protected <S, T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<S> entityClass,
|
||||
@@ -1907,8 +1916,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
T result = objectCallback.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDb(),
|
||||
collectionName)));
|
||||
T result = objectCallback
|
||||
.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName)));
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
@@ -1933,8 +1942,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param collectionName the collection to be queried
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback,
|
||||
CursorPreparer preparer, DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
|
||||
DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
|
||||
@@ -2024,8 +2033,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException("No Persistent Entity information found for the class "
|
||||
+ entityClass.getName());
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No Persistent Entity information found for the class " + entityClass.getName());
|
||||
}
|
||||
return entity.getCollection();
|
||||
}
|
||||
@@ -2089,8 +2098,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
String error = result.getErrorMessage();
|
||||
error = error == null ? "NO MESSAGE" : error;
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("Command execution failed: Error [" + error + "], Command = "
|
||||
+ source, ex);
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Command execution failed: Error [" + error + "], Command = " + source, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2286,7 +2295,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
class UnwrapAndReadDbObjectCallback<T> extends ReadDbObjectCallback<T> {
|
||||
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type, String collectionName) {
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type,
|
||||
String collectionName) {
|
||||
super(reader, type, collectionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,22 +17,30 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.BasicBSONObject;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Example.NullHandler;
|
||||
import org.springframework.data.domain.Example.StringMatcher;
|
||||
import org.springframework.data.domain.PropertySpecifier;
|
||||
import org.springframework.data.domain.ExampleSpec;
|
||||
import org.springframework.data.domain.ExampleSpec.NullHandler;
|
||||
import org.springframework.data.domain.ExampleSpec.PropertyValueTransformer;
|
||||
import org.springframework.data.domain.ExampleSpec.StringMatcher;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.MongoRegexCreator;
|
||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||
import org.springframework.data.repository.core.support.ExampleSpecAccessor;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -41,35 +49,43 @@ import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 1.8
|
||||
*/
|
||||
public class MongoExampleMapper {
|
||||
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
private final MongoConverter converter;
|
||||
private final Map<StringMatcher, Type> stringMatcherPartMapping = new HashMap<StringMatcher, Type>();
|
||||
|
||||
public MongoExampleMapper(MongoConverter converter) {
|
||||
|
||||
this.converter = converter;
|
||||
this.mappingContext = converter.getMappingContext();
|
||||
|
||||
stringMatcherPartMapping.put(StringMatcher.EXACT, Type.SIMPLE_PROPERTY);
|
||||
stringMatcherPartMapping.put(StringMatcher.CONTAINING, Type.CONTAINING);
|
||||
stringMatcherPartMapping.put(StringMatcher.STARTING, Type.STARTING_WITH);
|
||||
stringMatcherPartMapping.put(StringMatcher.ENDING, Type.ENDING_WITH);
|
||||
stringMatcherPartMapping.put(StringMatcher.REGEX, Type.REGEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
|
||||
* {@link Example#getProbe()}.
|
||||
*
|
||||
*
|
||||
* @param example
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
public DBObject getMappedExample(Example<?> example) {
|
||||
return getMappedExample(example, mappingContext.getPersistentEntity(example.getSampleType()));
|
||||
return getMappedExample(example, mappingContext.getPersistentEntity(example.getProbeType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
|
||||
* {@link Example#getProbe()}.
|
||||
*
|
||||
*
|
||||
* @param example
|
||||
* @param entity
|
||||
* @return
|
||||
@@ -77,21 +93,27 @@ public class MongoExampleMapper {
|
||||
*/
|
||||
public DBObject getMappedExample(Example<?> example, MongoPersistentEntity<?> entity) {
|
||||
|
||||
DBObject reference = (DBObject) converter.convertToMongoType(example.getSampleObject());
|
||||
DBObject reference = (DBObject) converter.convertToMongoType(example.getProbe());
|
||||
|
||||
if (entity.hasIdProperty() && entity.getIdentifierAccessor(example.getSampleObject()).getIdentifier() == null) {
|
||||
if (entity.hasIdProperty() && entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {
|
||||
reference.removeField(entity.getIdProperty().getFieldName());
|
||||
}
|
||||
|
||||
applyPropertySpecs("", reference, example);
|
||||
ExampleSpecAccessor exampleSpecAccessor = new ExampleSpecAccessor(example.getExampleSpec());
|
||||
|
||||
return ObjectUtils.nullSafeEquals(NullHandler.INCLUDE, example.getNullHandler()) ? reference : new BasicDBObject(
|
||||
SerializationUtils.flatMap(reference));
|
||||
applyPropertySpecs("", reference, example.getProbeType(), exampleSpecAccessor);
|
||||
|
||||
if (exampleSpecAccessor.isTyped()) {
|
||||
this.converter.getTypeMapper().writeTypeRestrictions(reference, (Set) Collections.singleton(example.getResultType()));
|
||||
}
|
||||
|
||||
return ObjectUtils.nullSafeEquals(NullHandler.INCLUDE, exampleSpecAccessor.getNullHandler()) ? reference
|
||||
: new BasicDBObject(SerializationUtils.flattenMap(reference));
|
||||
}
|
||||
|
||||
private String getMappedPropertyPath(String path, Example<?> example) {
|
||||
private String getMappedPropertyPath(String path, Class<?> probeType) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(example.getSampleType());
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(probeType);
|
||||
|
||||
Iterator<String> parts = Arrays.asList(path.split("\\.")).iterator();
|
||||
|
||||
@@ -136,7 +158,8 @@ public class MongoExampleMapper {
|
||||
|
||||
}
|
||||
|
||||
private void applyPropertySpecs(String path, DBObject source, Example<?> example) {
|
||||
private void applyPropertySpecs(String path, DBObject source, Class<?> probeType,
|
||||
ExampleSpecAccessor exampleSpecAccessor) {
|
||||
|
||||
if (!(source instanceof BasicDBObject)) {
|
||||
return;
|
||||
@@ -147,47 +170,37 @@ public class MongoExampleMapper {
|
||||
while (iter.hasNext()) {
|
||||
|
||||
Map.Entry<String, Object> entry = iter.next();
|
||||
|
||||
if (entry.getKey().equals("_id") && entry.getValue() == null) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
String propertyPath = StringUtils.hasText(path) ? path + "." + entry.getKey() : entry.getKey();
|
||||
|
||||
String mappedPropertyPath = getMappedPropertyPath(propertyPath, example);
|
||||
if (example.isIgnoredPath(propertyPath) || example.isIgnoredPath(mappedPropertyPath)) {
|
||||
String mappedPropertyPath = getMappedPropertyPath(propertyPath, probeType);
|
||||
|
||||
if(isEmptyIdProperty(entry)) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (exampleSpecAccessor.isIgnoredPath(propertyPath) || exampleSpecAccessor.isIgnoredPath(mappedPropertyPath)) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
PropertySpecifier specifier = null;
|
||||
StringMatcher stringMatcher = example.getDefaultStringMatcher();
|
||||
StringMatcher stringMatcher = exampleSpecAccessor.getDefaultStringMatcher();
|
||||
Object value = entry.getValue();
|
||||
boolean ignoreCase = example.isIngnoreCaseEnabled();
|
||||
boolean ignoreCase = exampleSpecAccessor.isIgnoreCaseEnabled();
|
||||
|
||||
if (example.hasPropertySpecifiers()) {
|
||||
if (exampleSpecAccessor.hasPropertySpecifiers()) {
|
||||
|
||||
mappedPropertyPath = example.hasPropertySpecifier(propertyPath) ? propertyPath : getMappedPropertyPath(
|
||||
propertyPath, example);
|
||||
mappedPropertyPath = exampleSpecAccessor.hasPropertySpecifier(propertyPath) ? propertyPath
|
||||
: getMappedPropertyPath(propertyPath, probeType);
|
||||
|
||||
specifier = example.getPropertySpecifier(mappedPropertyPath);
|
||||
|
||||
if (specifier != null) {
|
||||
if (specifier.hasStringMatcher()) {
|
||||
stringMatcher = specifier.getStringMatcher();
|
||||
}
|
||||
if (specifier.getIgnoreCase() != null) {
|
||||
ignoreCase = specifier.getIgnoreCase();
|
||||
}
|
||||
|
||||
}
|
||||
stringMatcher = exampleSpecAccessor.getStringMatcherForPath(mappedPropertyPath);
|
||||
ignoreCase = exampleSpecAccessor.isIgnoreCaseForPath(mappedPropertyPath);
|
||||
}
|
||||
|
||||
// TODO: should a PropertySpecifier outrule the later on string matching?
|
||||
if (specifier != null) {
|
||||
if (exampleSpecAccessor.hasPropertySpecifier(mappedPropertyPath)) {
|
||||
|
||||
value = specifier.transformValue(value);
|
||||
PropertyValueTransformer valueTransformer = exampleSpecAccessor.getValueTransformerForPath(mappedPropertyPath);
|
||||
value = valueTransformer.convert(value);
|
||||
if (value == null) {
|
||||
iter.remove();
|
||||
continue;
|
||||
@@ -199,11 +212,15 @@ public class MongoExampleMapper {
|
||||
if (entry.getValue() instanceof String) {
|
||||
applyStringMatcher(entry, stringMatcher, ignoreCase);
|
||||
} else if (entry.getValue() instanceof BasicDBObject) {
|
||||
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), example);
|
||||
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), probeType, exampleSpecAccessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmptyIdProperty(Entry<String, Object> entry) {
|
||||
return entry.getKey().equals("_id") && entry.getValue() == null;
|
||||
}
|
||||
|
||||
private void applyStringMatcher(Map.Entry<String, Object> entry, StringMatcher stringMatcher, boolean ignoreCase) {
|
||||
|
||||
BasicDBObject dbo = new BasicDBObject();
|
||||
@@ -216,8 +233,8 @@ public class MongoExampleMapper {
|
||||
}
|
||||
} else {
|
||||
|
||||
String expression = MongoRegexCreator.INSTANCE.toRegularExpression((String) entry.getValue(),
|
||||
stringMatcher.getPartType());
|
||||
Type type = stringMatcherPartMapping.get(stringMatcher);
|
||||
String expression = MongoRegexCreator.INSTANCE.toRegularExpression((String) entry.getValue(), type);
|
||||
dbo.put("$regex", expression);
|
||||
entry.setValue(dbo);
|
||||
}
|
||||
@@ -226,4 +243,5 @@ public class MongoExampleMapper {
|
||||
dbo.put("$options", "i");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -261,8 +261,8 @@ public class QueryMapper {
|
||||
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
|
||||
Object value = keyword.getValue();
|
||||
|
||||
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property) : getMappedValue(
|
||||
property.with(keyword.getKey()), value);
|
||||
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property)
|
||||
: getMappedValue(property.with(keyword.getKey()), value);
|
||||
|
||||
return new BasicDBObject(keyword.key, convertedValue);
|
||||
}
|
||||
@@ -484,8 +484,8 @@ public class QueryMapper {
|
||||
}
|
||||
|
||||
try {
|
||||
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService
|
||||
.convert(id, ObjectId.class) : delegateConvertToMongoType(id, null);
|
||||
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService.convert(id, ObjectId.class)
|
||||
: delegateConvertToMongoType(id, null);
|
||||
} catch (ConversionException o_O) {
|
||||
return delegateConvertToMongoType(id, null);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Criteria byExample(Object example) {
|
||||
return byExample(new Example<Object>(example));
|
||||
return byExample(Example.of(example));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum MongoRegexCreator {
|
||||
@@ -67,6 +68,10 @@ public enum MongoRegexCreator {
|
||||
|
||||
private String prepareAndEscapeStringBeforeApplyingLikeRegex(String source, Type type) {
|
||||
|
||||
if (ObjectUtils.nullSafeEquals(Type.REGEX, type)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.nullSafeEquals(Type.LIKE, type)) {
|
||||
return PUNCTATION_PATTERN.matcher(source).find() ? Pattern.quote(source) : source;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,7 +63,7 @@ public abstract class SerializationUtils {
|
||||
* @return {@link Collections#emptyMap()} when source is {@literal null}
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Map<String, Object> flatMap(DBObject source) {
|
||||
public static Map<String, Object> flattenMap(DBObject source) {
|
||||
|
||||
if (source == null) {
|
||||
return Collections.emptyMap();
|
||||
|
||||
@@ -19,21 +19,22 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||
|
||||
/**
|
||||
* Mongo specific {@link org.springframework.data.repository.Repository} interface.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
public interface MongoRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
|
||||
public interface MongoRepository<T, ID extends Serializable>
|
||||
extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -57,7 +58,7 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo
|
||||
* Inserts the given a given entity. Assumes the instance to be new to be able to apply insertion optimizations. Use
|
||||
* the returned instance for further operations as the save operation might have changed the entity instance
|
||||
* completely. Prefer using {@link #save(Object)} instead to avoid the usage of store-specific API.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return the saved entity
|
||||
* @since 1.7
|
||||
@@ -68,40 +69,21 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo
|
||||
* Inserts the given entities. Assumes the given entities to have not been persisted yet and thus will optimize the
|
||||
* insert over a call to {@link #save(Iterable)}. Prefer using {@link #save(Iterable)} to avoid the usage of store
|
||||
* specific API.
|
||||
*
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @return the saved entities
|
||||
* @since 1.7
|
||||
*/
|
||||
<S extends T> List<S> insert(Iterable<S> entities);
|
||||
|
||||
/**
|
||||
* Returns all instances of the type specified by the given {@link Example}.
|
||||
*
|
||||
* @param example must not be {@literal null}.
|
||||
* @return
|
||||
* @since 1.8
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
|
||||
*/
|
||||
<S extends T> List<T> findAllByExample(Example<S> example);
|
||||
<S extends T> List<S> findAll(Example<S> example);
|
||||
|
||||
/**
|
||||
* Returns all instances of the type specified by the given {@link Example}.
|
||||
*
|
||||
* @param example must not be {@literal null}.
|
||||
* @param sort can be {@literal null}.
|
||||
* @return all entities sorted by the given options
|
||||
* @since 1.8
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
<S extends T> List<T> findAllByExample(Example<S> example, Sort sort);
|
||||
<S extends T> List<S> findAll(Example<S> example, Sort sort);
|
||||
|
||||
/**
|
||||
* Returns a {@link Page} of entities meeting the paging restriction specified by the given {@link Example} limited to
|
||||
* criteria provided in the {@code Pageable} object.
|
||||
*
|
||||
* @param example must not be {@literal null}.
|
||||
* @param pageable can be {@literal null}.
|
||||
* @return a {@link Page} of entities
|
||||
* @since 1.8
|
||||
*/
|
||||
<S extends T> Page<T> findAllByExample(Example<S> example, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -133,11 +132,6 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getFullText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Example<?> getSampleObject() {
|
||||
return delegate.getSampleObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given value with the underlying {@link MongoWriter}.
|
||||
*
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -61,12 +60,4 @@ public interface MongoParameterAccessor extends ParameterAccessor {
|
||||
* @since 1.8
|
||||
*/
|
||||
Object[] getValues();
|
||||
|
||||
/**
|
||||
* Get the sample for query by example
|
||||
*
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
Example<?> getSampleObject();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -43,7 +42,6 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
private final int rangeIndex;
|
||||
private final int maxDistanceIndex;
|
||||
private final Integer fullTextIndex;
|
||||
private final int sampleObjectIndex;
|
||||
|
||||
private Integer nearIndex;
|
||||
|
||||
@@ -71,12 +69,10 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
} else if (this.nearIndex == null) {
|
||||
this.nearIndex = -1;
|
||||
}
|
||||
|
||||
this.sampleObjectIndex = parameterTypes.indexOf(Example.class);
|
||||
}
|
||||
|
||||
private MongoParameters(List<MongoParameter> parameters, int maxDistanceIndex, Integer nearIndex,
|
||||
Integer fullTextIndex, int rangeIndex, int sampleObjectIndex) {
|
||||
Integer fullTextIndex, int rangeIndex) {
|
||||
|
||||
super(parameters);
|
||||
|
||||
@@ -84,7 +80,6 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
this.fullTextIndex = fullTextIndex;
|
||||
this.maxDistanceIndex = maxDistanceIndex;
|
||||
this.rangeIndex = rangeIndex;
|
||||
this.sampleObjectIndex = sampleObjectIndex;
|
||||
}
|
||||
|
||||
private final int getNearIndex(List<Class<?>> parameterTypes) {
|
||||
@@ -187,22 +182,13 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
return rangeIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
public int getSampleObjectParameterIndex() {
|
||||
return sampleObjectIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.Parameters#createFrom(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
protected MongoParameters createFrom(List<MongoParameter> parameters) {
|
||||
return new MongoParameters(parameters, this.maxDistanceIndex, this.nearIndex, this.fullTextIndex, this.rangeIndex,
|
||||
this.sampleObjectIndex);
|
||||
return new MongoParameters(parameters, this.maxDistanceIndex, this.nearIndex, this.fullTextIndex, this.rangeIndex);
|
||||
}
|
||||
|
||||
private int getTypeIndex(List<TypeInformation<?>> parameterTypes, Class<?> type, Class<?> componentType) {
|
||||
@@ -254,7 +240,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
@Override
|
||||
public boolean isSpecialParameter() {
|
||||
return super.isSpecialParameter() || Distance.class.isAssignableFrom(getType()) || isNearParameter()
|
||||
|| TextCriteria.class.isAssignableFrom(getType()) || isExample();
|
||||
|| TextCriteria.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
private boolean isNearParameter() {
|
||||
@@ -274,10 +260,6 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
return parameter.getParameterAnnotation(Near.class) != null;
|
||||
}
|
||||
|
||||
private boolean isExample() {
|
||||
return Example.class.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.repository.query;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -126,15 +125,9 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
return ((TextCriteria) fullText);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Expected full text parameter to be one of String, Term or TextCriteria but found %s.",
|
||||
ClassUtils.getShortName(fullText.getClass())));
|
||||
}
|
||||
|
||||
public Example<?> getSampleObject() {
|
||||
|
||||
int index = method.getParameters().getSampleObjectParameterIndex();
|
||||
return index >= 0 ? (Example<?>) getValue(index) : null;
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected full text parameter to be one of String, Term or TextCriteria but found %s.",
|
||||
ClassUtils.getShortName(fullText.getClass())));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -151,20 +151,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
@Override
|
||||
protected Query complete(Criteria criteria, Sort sort) {
|
||||
|
||||
Criteria toUse = null;
|
||||
if (accessor.getSampleObject() != null) {
|
||||
toUse = new Criteria().alike(accessor.getSampleObject());
|
||||
}
|
||||
|
||||
if (criteria != null) {
|
||||
if (toUse == null) {
|
||||
toUse = criteria;
|
||||
} else {
|
||||
toUse.andOperator(criteria);
|
||||
}
|
||||
}
|
||||
|
||||
Query query = (toUse == null ? new Query() : new Query(toUse)).with(sort);
|
||||
Query query = (criteria == null ? new Query() : new Query(criteria)).with(sort);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Created query " + query);
|
||||
@@ -298,8 +285,8 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
case ALWAYS:
|
||||
if (path.getType() != String.class) {
|
||||
throw new IllegalArgumentException(String.format("Part %s must be of type String but was %s", path,
|
||||
path.getType()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Part %s must be of type String but was %s", path, path.getType()));
|
||||
}
|
||||
// fall-through
|
||||
|
||||
@@ -385,8 +372,8 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
return (T) parameter;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Expected parameter type of %s but got %s!", type,
|
||||
parameter.getClass()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected parameter type of %s but got %s!", type, parameter.getClass()));
|
||||
}
|
||||
|
||||
private Object[] nextAsArray(Iterator<Object> iterator) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.TypedExampleSpec;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class SimpleMongoRepository<T, ID extends Serializable> implements MongoRepository<T, ID> {
|
||||
|
||||
@@ -54,7 +56,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
* Creates a new {@link SimpleMongoRepository} for the given {@link MongoEntityInformation} and {@link MongoTemplate}.
|
||||
*
|
||||
* @param metadata must not be {@literal null}.
|
||||
* @param template must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
*/
|
||||
public SimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
|
||||
|
||||
@@ -265,18 +267,18 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
* @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example, org.springframework.data.domain.Pageable)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> Page<T> findAllByExample(Example<S> example, Pageable pageable) {
|
||||
public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
|
||||
|
||||
Assert.notNull(example, "Sample must not be null!");
|
||||
|
||||
Query q = new Query(new Criteria().alike(example)).with(pageable);
|
||||
|
||||
long count = mongoOperations.count(q, entityInformation.getJavaType(), entityInformation.getCollectionName());
|
||||
long count = mongoOperations.count(q, getResultType(example), entityInformation.getCollectionName());
|
||||
if (count == 0) {
|
||||
return new PageImpl<T>(Collections.<T> emptyList());
|
||||
return new PageImpl<S>(Collections.<S> emptyList());
|
||||
}
|
||||
return new PageImpl<T>(mongoOperations.find(q, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName()), pageable, count);
|
||||
return new PageImpl<S>(mongoOperations.find(q, getResultType(example), entityInformation.getCollectionName()), pageable,
|
||||
count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -284,7 +286,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
* @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> List<T> findAllByExample(Example<S> example, Sort sort) {
|
||||
public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
|
||||
|
||||
Assert.notNull(example, "Sample must not be null!");
|
||||
|
||||
@@ -294,7 +296,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
q.with(sort);
|
||||
}
|
||||
|
||||
return findAll(q);
|
||||
return mongoOperations.find(q, getResultType(example), entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -302,13 +304,56 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
* @see org.springframework.data.mongodb.repository.MongoRepository#findAllByExample(org.springframework.data.domain.Example)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> List<T> findAllByExample(Example<S> example) {
|
||||
public <S extends T> List<S> findAll(Example<S> example) {
|
||||
return findAll(example, (Sort) null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findOne(org.springframework.data.domain.Example)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> S findOne(Example<S> example) {
|
||||
|
||||
Assert.notNull(example, "Sample must not be null!");
|
||||
|
||||
Query q = new Query(new Criteria().alike(example));
|
||||
return mongoOperations.findOne(q, getResultType(example), entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
return findAll(q);
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryByExampleExecutor#count(org.springframework.data.domain.Example)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> long count(Example<S> example) {
|
||||
|
||||
Assert.notNull(example, "Sample must not be null!");
|
||||
|
||||
Query q = new Query(new Criteria().alike(example));
|
||||
return mongoOperations.count(q, getResultType(example), entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryByExampleExecutor#exists(org.springframework.data.domain.Example)
|
||||
*/
|
||||
@Override
|
||||
public <S extends T> boolean exists(Example<S> example) {
|
||||
|
||||
Assert.notNull(example, "Sample must not be null!");
|
||||
|
||||
Query q = new Query(new Criteria().alike(example));
|
||||
return mongoOperations.exists(q, getResultType(example), entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
private <S extends T> Class<S> getResultType(Example<S> example) {
|
||||
|
||||
if (example.getExampleSpec() instanceof TypedExampleSpec<?>) {
|
||||
return example.getResultType();
|
||||
}
|
||||
|
||||
return (Class<S>) entityInformation.getJavaType();
|
||||
}
|
||||
|
||||
private List<T> findAll(Query query) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,8 +23,6 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.collection.IsMapContaining;
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||
|
||||
@@ -70,68 +68,68 @@ public class SerializationUtilsUnitTests {
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void flatMapShouldFlatOutNestedStructureCorrectly() {
|
||||
public void flattenMapShouldFlatOutNestedStructureCorrectly() {
|
||||
|
||||
DBObject dbo = new BasicDBObjectBuilder().add("_id", 1).add("nested", new BasicDBObject("value", "conflux")).get();
|
||||
|
||||
assertThat(flatMap(dbo), IsMapContaining.<String, Object> hasEntry("_id", 1));
|
||||
assertThat(flatMap(dbo), IsMapContaining.<String, Object> hasEntry("nested.value", "conflux"));
|
||||
assertThat(flattenMap(dbo), hasEntry("_id", (Object) 1));
|
||||
assertThat(flattenMap(dbo), hasEntry("nested.value", (Object) "conflux"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void flatMapShouldFlatOutNestedStructureWithListCorrectly() {
|
||||
public void flattenMapShouldFlatOutNestedStructureWithListCorrectly() {
|
||||
|
||||
BasicDBList dbl = new BasicDBList();
|
||||
dbl.addAll(Arrays.asList("nightwielder", "calamity"));
|
||||
|
||||
DBObject dbo = new BasicDBObjectBuilder().add("_id", 1).add("nested", new BasicDBObject("value", dbl)).get();
|
||||
|
||||
assertThat(flatMap(dbo), IsMapContaining.<String, Object> hasEntry("_id", 1));
|
||||
assertThat(flatMap(dbo), IsMapContaining.<String, Object> hasEntry("nested.value", dbl));
|
||||
assertThat(flattenMap(dbo), hasEntry("_id", (Object) 1));
|
||||
assertThat(flattenMap(dbo), hasEntry("nested.value", (Object) dbl));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void flatMapShouldLeaveKeywordsUntouched() {
|
||||
public void flattenMapShouldLeaveKeywordsUntouched() {
|
||||
|
||||
DBObject dbo = new BasicDBObjectBuilder().add("_id", 1).add("nested", new BasicDBObject("$regex", "^conflux$"))
|
||||
.get();
|
||||
|
||||
Map<String, Object> map = flatMap(dbo);
|
||||
Map<String, Object> map = flattenMap(dbo);
|
||||
|
||||
assertThat(map, IsMapContaining.<String, Object> hasEntry("_id", 1));
|
||||
assertThat(map, hasEntry("_id", (Object) 1));
|
||||
assertThat(map.get("nested"), notNullValue());
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$regex"), Is.<Object> is("^conflux$"));
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$regex"), is((Object) "^conflux$"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void flatMapSouldAppendCommandsCorrectly() {
|
||||
public void flattenMapShouldAppendCommandsCorrectly() {
|
||||
|
||||
DBObject dbo = new BasicDBObjectBuilder().add("_id", 1)
|
||||
.add("nested", new BasicDBObjectBuilder().add("$regex", "^conflux$").add("$options", "i").get()).get();
|
||||
|
||||
Map<String, Object> map = flatMap(dbo);
|
||||
Map<String, Object> map = flattenMap(dbo);
|
||||
|
||||
assertThat(map, IsMapContaining.<String, Object> hasEntry("_id", 1));
|
||||
assertThat(map, hasEntry("_id", (Object) 1));
|
||||
assertThat(map.get("nested"), notNullValue());
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$regex"), Is.<Object> is("^conflux$"));
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$options"), Is.<Object> is("i"));
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$regex"), is((Object) "^conflux$"));
|
||||
assertThat(((Map<String, Object>) map.get("nested")).get("$options"), is((Object) "i"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void flatMapShouldReturnEmptyMapWhenSourceIsNull() {
|
||||
assertThat(flatMap(null).isEmpty(), is(true));
|
||||
public void flattenMapShouldReturnEmptyMapWhenSourceIsNull() {
|
||||
assertThat(flattenMap(null).isEmpty(), is(true));
|
||||
}
|
||||
|
||||
static class Complex {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.Example.*;
|
||||
import static org.springframework.data.domain.PropertySpecifier.*;
|
||||
import static org.springframework.data.mongodb.core.DBObjectTestUtils.*;
|
||||
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
|
||||
|
||||
@@ -34,6 +33,9 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.ExampleSpec;
|
||||
import org.springframework.data.domain.ExampleSpec.GenericPropertyMatcher;
|
||||
import org.springframework.data.domain.ExampleSpec.StringMatcher;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapperUnitTests.ClassWithGeoTypes;
|
||||
@@ -49,6 +51,7 @@ import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoExampleMapperUnitTests {
|
||||
@@ -79,7 +82,7 @@ public class MongoExampleMapperUnitTests {
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.id = "steelheart";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("_id", "steelheart").get()));
|
||||
}
|
||||
@@ -95,11 +98,10 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder().add("_id", "steelheart").add("stringValue", "firefight").add("intValue", 100)
|
||||
.get()));
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("_id", "steelheart").add("stringValue", "firefight")
|
||||
.add("intValue", 100).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +114,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", "firefight").add("intValue", 100).get()));
|
||||
}
|
||||
@@ -126,7 +128,7 @@ public class MongoExampleMapperUnitTests {
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.listOfString = Arrays.asList("Prof", "Tia", "David");
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("listOfString", Arrays.asList("Prof", "Tia", "David")).get()));
|
||||
}
|
||||
@@ -140,7 +142,7 @@ public class MongoExampleMapperUnitTests {
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.customNamedField = "Mitosis";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("custom_field_name", "Mitosis").get()));
|
||||
}
|
||||
@@ -149,13 +151,30 @@ public class MongoExampleMapperUnitTests {
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenienMatchMode() {
|
||||
public void typedExampleShouldContainTypeRestriction() {
|
||||
|
||||
WrapperDocument probe = new WrapperDocument();
|
||||
probe.flatDoc = new FlatDocument();
|
||||
probe.flatDoc.stringValue = "conflux";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(WrapperDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe, ExampleSpec.typed(WrapperDocument.class)),
|
||||
context.getPersistentEntity(WrapperDocument.class));
|
||||
|
||||
assertThat(dbo,
|
||||
isBsonObject().containing("_class", new BasicDBObject("$in", new String[] { probe.getClass().getName() })));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenientMatchMode() {
|
||||
|
||||
WrapperDocument probe = new WrapperDocument();
|
||||
probe.flatDoc = new FlatDocument();
|
||||
probe.flatDoc.stringValue = "conflux";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(WrapperDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("flatDoc.stringValue", "conflux").get()));
|
||||
}
|
||||
@@ -164,13 +183,13 @@ public class MongoExampleMapperUnitTests {
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStriktMatchMode() {
|
||||
public void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStrictMatchMode() {
|
||||
|
||||
WrapperDocument probe = new WrapperDocument();
|
||||
probe.flatDoc = new FlatDocument();
|
||||
probe.flatDoc.stringValue = "conflux";
|
||||
|
||||
Example<?> example = newExampleOf(probe).includeNullValues().get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIncludeNullValues());
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class));
|
||||
|
||||
@@ -187,13 +206,30 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
Example<?> example = newExampleOf(probe).matchStringsStartingWith().get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withStringMatcher(StringMatcher.STARTING));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", "^firefight"))
|
||||
.add("intValue", 100).get()));
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", "^firefight"))
|
||||
.add("intValue", 100).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void exampleShouldBeMappedCorrectlyForFlatTypeContainingDotsWhenStringMatchModeIsStarting() {
|
||||
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.stringValue = "fire.ight";
|
||||
probe.intValue = 100;
|
||||
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withStringMatcherStarting());
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder()
|
||||
.add("stringValue", new BasicDBObject("$regex", "^" + Pattern.quote("fire.ight"))).add("intValue", 100).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +242,30 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
Example<?> example = newExampleOf(probe).matchStringsEndingWith().get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withStringMatcher(StringMatcher.ENDING));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", "firefight$"))
|
||||
.add("intValue", 100).get()));
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", "firefight$"))
|
||||
.add("intValue", 100).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeRegex() {
|
||||
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.stringValue = "firefight";
|
||||
probe.customNamedField = "^(cat|dog).*shelter\\d?";
|
||||
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withStringMatcher(StringMatcher.REGEX));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", "firefight"))
|
||||
.add("custom_field_name", new BasicDBObject("$regex", "^(cat|dog).*shelter\\d?")).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,12 +278,12 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
Example<?> example = newExampleOf(probe).matchStringsEndingWith().matchStringsWithIgnoreCase().get();
|
||||
Example<?> example = Example.of(probe,
|
||||
ExampleSpec.untyped().withStringMatcher(StringMatcher.ENDING).withIgnoreCase());
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(
|
||||
dbo,
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder()
|
||||
.add("stringValue", new BasicDBObjectBuilder().add("$regex", "firefight$").add("$options", "i").get())
|
||||
.add("intValue", 100).get()));
|
||||
@@ -246,12 +299,11 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.intValue = 100;
|
||||
|
||||
Example<?> example = newExampleOf(probe).matchStringsWithIgnoreCase().get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIgnoreCase());
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(
|
||||
dbo,
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder()
|
||||
.add("stringValue",
|
||||
new BasicDBObjectBuilder().add("$regex", Pattern.quote("firefight")).add("$options", "i").get())
|
||||
@@ -269,7 +321,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.referenceDocument = new ReferenceDocument();
|
||||
probe.referenceDocument.id = "200";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
com.mongodb.DBRef reference = getTypedValue(dbo, "referenceDocument", com.mongodb.DBRef.class);
|
||||
|
||||
assertThat(reference.getId(), Is.<Object> is("200"));
|
||||
@@ -285,7 +337,7 @@ public class MongoExampleMapperUnitTests {
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.stringValue = "steelheart";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", "steelheart").get()));
|
||||
}
|
||||
@@ -299,7 +351,7 @@ public class MongoExampleMapperUnitTests {
|
||||
ClassWithGeoTypes probe = new ClassWithGeoTypes();
|
||||
probe.legacyPoint = new Point(10D, 20D);
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
|
||||
assertThat(dbo.get("legacyPoint.x"), Is.<Object> is(10D));
|
||||
assertThat(dbo.get("legacyPoint.y"), Is.<Object> is(20D));
|
||||
@@ -316,7 +368,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.intValue = 10;
|
||||
probe.stringValue = "string";
|
||||
|
||||
Example<?> example = newExampleOf(probe).ignore("customNamedField").get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIgnorePaths("customNamedField"));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
@@ -334,7 +386,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.intValue = 10;
|
||||
probe.stringValue = "string";
|
||||
|
||||
Example<?> example = newExampleOf(probe).ignore("stringValue").get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIgnorePaths("stringValue"));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
@@ -353,12 +405,12 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.flatDoc.intValue = 10;
|
||||
probe.flatDoc.stringValue = "string";
|
||||
|
||||
Example<?> example = newExampleOf(probe).ignore("flatDoc.stringValue").get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIgnorePaths("flatDoc.stringValue"));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("flatDoc.custom_field_name", "foo").add("flatDoc.intValue", 10)
|
||||
.get()));
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder().add("flatDoc.custom_field_name", "foo").add("flatDoc.intValue", 10).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,12 +425,12 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.flatDoc.intValue = 10;
|
||||
probe.flatDoc.stringValue = "string";
|
||||
|
||||
Example<?> example = newExampleOf(probe).ignore("flatDoc.customNamedField").get();
|
||||
Example<?> example = Example.of(probe, ExampleSpec.untyped().withIgnorePaths("flatDoc.customNamedField"));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class));
|
||||
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("flatDoc.stringValue", "string").add("flatDoc.intValue", 10)
|
||||
.get()));
|
||||
assertThat(dbo,
|
||||
is(new BasicDBObjectBuilder().add("flatDoc.stringValue", "string").add("flatDoc.intValue", 10).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,15 +443,13 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.stringValue = "firefight";
|
||||
probe.customNamedField = "steelheart";
|
||||
|
||||
Example<?> example = newExampleOf(probe).specify(newPropertySpecifier("stringValue").matchStringContaining().get())
|
||||
.get();
|
||||
Example<?> example = Example.of(probe,
|
||||
ExampleSpec.untyped().withMatcher("stringValue", new GenericPropertyMatcher().contains()));
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(
|
||||
dbo,
|
||||
is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", ".*firefight.*"))
|
||||
.add("custom_field_name", "steelheart").get()));
|
||||
assertThat(dbo, is(new BasicDBObjectBuilder().add("stringValue", new BasicDBObject("$regex", ".*firefight.*"))
|
||||
.add("custom_field_name", "steelheart").get()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,7 +463,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.customNamedField = "steelheart";
|
||||
probe.anotherStringValue = "calamity";
|
||||
|
||||
DBObject dbo = mapper.getMappedExample(exampleOf(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
DBObject dbo = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("anotherStringValue", "calamity"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,10 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class QueryByExampleTests {
|
||||
|
||||
MongoTemplate template;
|
||||
@@ -54,7 +58,9 @@ public class QueryByExampleTests {
|
||||
Person sample = new Person();
|
||||
sample.lastname = "stark";
|
||||
|
||||
List<Person> result = template.findByExample(sample);
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(2));
|
||||
}
|
||||
|
||||
@@ -70,7 +76,9 @@ public class QueryByExampleTests {
|
||||
sample.lastname = "stark";
|
||||
sample.firstname = "arya";
|
||||
|
||||
List<Person> result = template.findByExample(sample);
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(1));
|
||||
}
|
||||
|
||||
@@ -88,7 +96,9 @@ public class QueryByExampleTests {
|
||||
Person sample = new Person();
|
||||
sample.id = p4.id;
|
||||
|
||||
List<Person> result = template.findByExample(sample);
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(1));
|
||||
}
|
||||
|
||||
@@ -104,7 +114,10 @@ public class QueryByExampleTests {
|
||||
sample.firstname = "jon";
|
||||
sample.firstname = "stark";
|
||||
|
||||
List<Person> result = template.findByExample(sample);
|
||||
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(0));
|
||||
}
|
||||
|
||||
@@ -118,7 +131,9 @@ public class QueryByExampleTests {
|
||||
|
||||
Person sample = new Person();
|
||||
|
||||
List<Person> result = template.findByExample(sample);
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(3));
|
||||
}
|
||||
|
||||
@@ -133,7 +148,7 @@ public class QueryByExampleTests {
|
||||
Person sample = new Person();
|
||||
sample.lastname = "stark";
|
||||
|
||||
Query query = new Query(new Criteria().alike(new Example<Person>(sample)).and("firstname").regex("^ary*"));
|
||||
Query query = new Query(new Criteria().alike(Example.of(sample)).and("firstname").regex("^ary*"));
|
||||
|
||||
List<Person> result = template.find(query, Person.class);
|
||||
Assert.assertThat(result.size(), Is.is(1));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,8 +28,6 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@@ -66,6 +64,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@@ -179,8 +178,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void executesPagedFinderCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname",
|
||||
"firstname"));
|
||||
Page<Person> page = repository.findByLastnameLike("*a*",
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -190,8 +189,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void executesPagedFinderWithAnnotatedQueryCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC,
|
||||
"lastname", "firstname"));
|
||||
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*",
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -315,8 +314,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void findsPagedPeopleByPredicate() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findAll(person.lastname.contains("a"), new PageRequest(0, 2, Direction.ASC,
|
||||
"lastname"));
|
||||
Page<Person> page = repository.findAll(person.lastname.contains("a"),
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -402,8 +401,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS));
|
||||
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
}
|
||||
|
||||
@@ -414,8 +413,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(0, 20));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(0, 20));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
|
||||
// DATAMONGO-607
|
||||
@@ -625,8 +624,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
|
||||
repository.save(Arrays.asList(dave, oliver, carter, boyd, leroi));
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(2));
|
||||
@@ -650,8 +649,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
|
||||
repository.save(Arrays.asList(dave, oliver, carter));
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(1));
|
||||
assertThat(results.isFirst(), is(false));
|
||||
@@ -669,8 +668,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(0, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(0, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(1));
|
||||
@@ -688,8 +687,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(new Point(-73.99171, 40.738868));
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(true));
|
||||
assertThat(results.getNumberOfElements(), is(0));
|
||||
@@ -939,8 +938,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldLimitCollectionQueryToMaxResultsWhenPresent() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
List<Person> result = repository.findTop3ByLastnameStartingWith("Dylan");
|
||||
assertThat(result.size(), is(3));
|
||||
}
|
||||
@@ -951,8 +950,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(0, 2));
|
||||
assertThat(result.getContent().size(), is(2));
|
||||
}
|
||||
@@ -963,8 +962,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldLimitPagedQueryWhenPageRequestExceedsUpperBoundary() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(1, 2));
|
||||
assertThat(result.getContent().size(), is(1));
|
||||
}
|
||||
@@ -975,8 +974,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(2, 2));
|
||||
assertThat(result.getContent().size(), is(0));
|
||||
}
|
||||
@@ -1240,8 +1239,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
ReflectionTestUtils.setField(sample, "createdAt", null);
|
||||
ReflectionTestUtils.setField(sample, "email", null);
|
||||
|
||||
Page<Person> result = repository.findAllByExample(new Example<Person>(sample), new PageRequest(0, 10));
|
||||
Assert.assertThat(result.getNumberOfElements(), Is.is(2));
|
||||
Page<Person> result = repository.findAll(Example.of(sample), new PageRequest(0, 10));
|
||||
assertThat(result.getNumberOfElements(), is(2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,8 +1257,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
ReflectionTestUtils.setField(sample, "createdAt", null);
|
||||
ReflectionTestUtils.setField(sample, "email", null);
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
Assert.assertThat(result.size(), Is.is(2));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
assertThat(result.size(), is(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
||||
@Document
|
||||
public abstract class Contact {
|
||||
|
||||
@Id protected String id;
|
||||
@Id
|
||||
protected final String id;
|
||||
|
||||
public Contact() {
|
||||
this.id = new ObjectId().toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,11 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.ExampleSpec;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -27,6 +31,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* Integration tests for {@link ContactRepository}. Mostly related to mapping inheritance.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("config/MongoNamespaceIntegrationTests-context.xml")
|
||||
@@ -35,6 +40,11 @@ public class ContactRepositoryIntegrationTests {
|
||||
@Autowired
|
||||
ContactRepository repository;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readsAndWritesContactCorrectly() {
|
||||
|
||||
@@ -43,4 +53,46 @@ public class ContactRepositoryIntegrationTests {
|
||||
|
||||
assertTrue(repository.findOne(result.getId().toString()) instanceof Person);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void findsContactByUntypedExample() {
|
||||
|
||||
Person person = new Person("Oliver", "Gierke");
|
||||
Contact result = repository.save(person);
|
||||
|
||||
Example<Person> example = Example.of(person, ExampleSpec.untyped());
|
||||
|
||||
assertThat(repository.findOne(example), instanceOf(Person.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void findsContactByTypedExample() {
|
||||
|
||||
Person person = new Person("Oliver", "Gierke");
|
||||
Contact result = repository.save(person);
|
||||
|
||||
Example<Person> example = Example.of(person, ExampleSpec.typed(Person.class));
|
||||
|
||||
assertThat(repository.findOne(example), instanceOf(Person.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void findsNoContactByExample() {
|
||||
|
||||
Person person = new Person("Oliver", "Gierke");
|
||||
Contact result = repository.save(person);
|
||||
|
||||
Example<Person> example = Example.of(person, ExampleSpec.typed(Contact.class));
|
||||
|
||||
assertThat(repository.findOne(example), is(nullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,23 +334,22 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
|
||||
*/
|
||||
@Query("{ firstname : { $in : ?0 }}")
|
||||
Stream<Person> findByCustomQueryWithStreamingCursorByFirstnames(List<String> firstnames);
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : ?#{[0]}}")
|
||||
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly(String firstname);
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : ?#{[0]}, email: ?#{principal.email} }")
|
||||
List<Person> findWithSpelByFirstnameAndCurrentUserWithCustomQuery(String firstname);
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : :#{#firstname}}")
|
||||
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterVariableOnly(@Param("firstname") String firstname);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.repository.query;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -148,13 +147,4 @@ class StubParameterAccessor implements MongoParameterAccessor {
|
||||
public Class<?> getDynamicProjection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoParameterAccessor#getSampleObject()
|
||||
*/
|
||||
@Override
|
||||
public Example<?> getSampleObject() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.ExampleSpec;
|
||||
import org.springframework.data.domain.ExampleSpec.StringMatcher;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -51,6 +53,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
* @author <a href="mailto:kowsercse@gmail.com">A. B. M. Kowser</a>
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
@@ -130,7 +133,7 @@ public class SimpleMongoRepositoryTests {
|
||||
* @see DATAMONGO-1054
|
||||
*/
|
||||
@Test
|
||||
public void shouldInsertMutlipleFromList() {
|
||||
public void shouldInsertMultipleFromList() {
|
||||
|
||||
String randomId = UUID.randomUUID().toString();
|
||||
Map<String, Person> idToPerson = new HashMap<String, Person>();
|
||||
@@ -180,7 +183,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
Page<Person> result = repository.findAllByExample(new Example<Person>(sample), new PageRequest(0, 10));
|
||||
Page<Person> result = repository.findAll(Example.of(sample), new PageRequest(0, 10));
|
||||
|
||||
assertThat(result.getContent(), hasItems(dave, oliver));
|
||||
assertThat(result.getContent(), hasSize(2));
|
||||
@@ -196,9 +199,9 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItems(dave, oliver));
|
||||
assertThat(result, containsInAnyOrder(dave, oliver));
|
||||
assertThat(result, hasSize(2));
|
||||
}
|
||||
|
||||
@@ -218,7 +221,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setAddress(dave.getAddress());
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItem(dave));
|
||||
assertThat(result, hasSize(1));
|
||||
@@ -240,7 +243,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setAddress(new Address(null, null, "Washington"));
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItems(dave, oliver));
|
||||
assertThat(result, hasSize(2));
|
||||
@@ -259,7 +262,8 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setAddress(new Address(null, null, "Washington"));
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(Example.newExampleOf(sample).includeNullValues().get());
|
||||
Example<Person> example = Example.of(sample, ExampleSpec.typed(Person.class).withIncludeNullValues());
|
||||
List<Person> result = repository.findAll(example);
|
||||
|
||||
assertThat(result, empty());
|
||||
}
|
||||
@@ -277,7 +281,8 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setAddress(dave.getAddress());
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(Example.newExampleOf(sample).includeNullValues().get());
|
||||
Example<Person> example = Example.of(sample, ExampleSpec.untyped().withIncludeNullValues());
|
||||
List<Person> result = repository.findAll(example);
|
||||
|
||||
assertThat(result, hasItem(dave));
|
||||
assertThat(result, hasSize(1));
|
||||
@@ -293,7 +298,8 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLastname("Mat");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(Example.newExampleOf(sample).matchStringsStartingWith().get());
|
||||
Example<Person> example = Example.of(sample, ExampleSpec.untyped().withStringMatcher(StringMatcher.STARTING));
|
||||
List<Person> result = repository.findAll(example);
|
||||
|
||||
assertThat(result, hasItems(dave, oliver));
|
||||
assertThat(result, hasSize(2));
|
||||
@@ -319,7 +325,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setCreator(user);
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItem(megan));
|
||||
assertThat(result, hasSize(1));
|
||||
@@ -340,7 +346,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLocation(megan.getLocation());
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItem(megan));
|
||||
assertThat(result, hasSize(1));
|
||||
@@ -361,7 +367,7 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLocation(megan.getLocation());
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<Person>(sample));
|
||||
List<Person> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItem(megan));
|
||||
assertThat(result, hasSize(1));
|
||||
@@ -377,12 +383,59 @@ public class SimpleMongoRepositoryTests {
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
List<Person> result = repository.findAllByExample(new Example<PersonExtended>(sample));
|
||||
List<PersonExtended> result = repository.findAll(Example.of(sample));
|
||||
|
||||
assertThat(result, hasItems(dave, oliver));
|
||||
assertThat(result, containsInAnyOrder(dave, oliver));
|
||||
assertThat(result, hasSize(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void findOneByExampleShouldLookUpEntriesCorrectly() {
|
||||
|
||||
Person sample = new Person();
|
||||
sample.setFirstname("Dave");
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
Person result = repository.findOne(Example.of(sample));
|
||||
|
||||
assertThat(result, is(equalTo(dave)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void existsByExampleShouldLookUpEntriesCorrectly() {
|
||||
|
||||
Person sample = new Person();
|
||||
sample.setFirstname("Dave");
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
boolean result = repository.exists(Example.of(sample));
|
||||
|
||||
assertThat(result, is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1245
|
||||
*/
|
||||
@Test
|
||||
public void countByExampleShouldLookUpEntriesCorrectly() {
|
||||
|
||||
Person sample = new Person();
|
||||
sample.setLastname("Matthews");
|
||||
trimDomainType(sample, "id", "createdAt", "email");
|
||||
|
||||
long result = repository.count(Example.of(sample));
|
||||
|
||||
assertThat(result, is(equalTo(2L)));
|
||||
}
|
||||
|
||||
@Document(collection = "customizedPerson")
|
||||
static class PersonExtended extends Person {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
= Spring Data MongoDB - Reference Documentation
|
||||
Mark Pollack; Thomas Risberg; Oliver Gierke; Costin Leau; Jon Brisbin; Thomas Darimont; Christoph Strobl
|
||||
Mark Pollack; Thomas Risberg; Oliver Gierke; Costin Leau; Jon Brisbin; Thomas Darimont; Christoph Strobl; Mark Paluch
|
||||
:revnumber: {version}
|
||||
:revdate: {localdate}
|
||||
:toc:
|
||||
|
||||
@@ -1330,6 +1330,10 @@ TextQuery.searching(new TextCriteria().matching("\"coffee cake\""));
|
||||
TextQuery.searching(new TextCriteria().phrase("coffee cake"));
|
||||
----
|
||||
|
||||
include::../{spring-data-commons-docs}/query-by-example.adoc[]
|
||||
include::query-by-example.adoc[]
|
||||
|
||||
|
||||
[[mongo.mapreduce]]
|
||||
== Map-Reduce Operations
|
||||
|
||||
|
||||
71
src/main/asciidoc/reference/query-by-example.adoc
Normal file
71
src/main/asciidoc/reference/query-by-example.adoc
Normal file
@@ -0,0 +1,71 @@
|
||||
[[query.by.example.execution]]
|
||||
=== Executing Example
|
||||
|
||||
.Query by Example using a Repository
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
public interface PersonRepository extends QueryByExampleExecutor<Person> {
|
||||
|
||||
}
|
||||
|
||||
public class PersonService {
|
||||
|
||||
@Autowired PersonRepository personRepository;
|
||||
|
||||
public List<Person> findPeople(Person probe) {
|
||||
return personRepository.findAll(Example.of(probe));
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
An `Example` containing an untyped `ExampleSpec` uses the Repository type and its collection name. Typed `ExampleSpec` use their type as result type and the collection name from the Repository.
|
||||
|
||||
NOTE: When including `null` values in the `ExampleSpec` Spring Data Mongo uses embedded document matching instead of dot notation property matching. This forces exact document matching for all property values and the property order in the embedded document.
|
||||
|
||||
Spring Data MongoDB provides support for the following matching options:
|
||||
|
||||
[cols="1,2", options="header"]
|
||||
.`StringMatcher` options
|
||||
|===
|
||||
| Matching
|
||||
| Logical result
|
||||
|
||||
| `DEFAULT` (case-sensitive)
|
||||
| `{"firstname" : firstname}`
|
||||
|
||||
| `DEFAULT` (case-insensitive)
|
||||
| `{"firstname" : { $regex: firstname, $options: 'i'}}`
|
||||
|
||||
| `EXACT` (case-sensitive)
|
||||
| `{"firstname" : { $regex: /^firstname$/}}`
|
||||
|
||||
| `EXACT` (case-insensitive)
|
||||
| `{"firstname" : { $regex: /^firstname$/, $options: 'i'}}`
|
||||
|
||||
| `STARTING` (case-sensitive)
|
||||
| `{"firstname" : { $regex: /^firstname/}}`
|
||||
|
||||
| `STARTING` (case-insensitive)
|
||||
| `{"firstname" : { $regex: /^firstname/, $options: 'i'}}`
|
||||
|
||||
| `ENDING` (case-sensitive)
|
||||
| `{"firstname" : { $regex: /firstname$/}}`
|
||||
|
||||
| `ENDING` (case-insensitive)
|
||||
| `{"firstname" : { $regex: /firstname$/, $options: 'i'}}`
|
||||
|
||||
| `CONTAINING` (case-sensitive)
|
||||
| `{"firstname" : { $regex: /.\*firstname.*/}}`
|
||||
|
||||
| `CONTAINING` (case-insensitive)
|
||||
| `{"firstname" : { $regex: /.\*firstname.*/, $options: 'i'}}`
|
||||
|
||||
| `REGEX` (case-sensitive)
|
||||
| `{"firstname" : { $regex: /firstname/}}`
|
||||
|
||||
| `REGEX` (case-insensitive)
|
||||
| `{"firstname" : { $regex: /firstname/, $options: 'i'}}`
|
||||
|
||||
|===
|
||||
Reference in New Issue
Block a user