DATAMONGO-1730 - Adapt to API changes in mapping subsystem.
This commit is contained in:
@@ -17,22 +17,10 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
|
||||
import static org.springframework.data.util.Optionals.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bson.Document;
|
||||
@@ -60,11 +48,10 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
|
||||
import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext;
|
||||
@@ -558,8 +545,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.notNull(mode, "BulkMode must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
DefaultBulkOperations operations = new DefaultBulkOperations(this, collectionName,
|
||||
new BulkOperationContext(mode, getPersistentEntity(entityType), queryMapper, updateMapper));
|
||||
DefaultBulkOperations operations = new DefaultBulkOperations(this, collectionName, new BulkOperationContext(mode,
|
||||
Optional.ofNullable(getPersistentEntity(entityType)), queryMapper, updateMapper));
|
||||
|
||||
operations.setExceptionTranslator(exceptionTranslator);
|
||||
operations.setDefaultWriteConcern(writeConcern);
|
||||
@@ -640,9 +627,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
|
||||
String idKey = mappingContext.getPersistentEntity(entityClass)//
|
||||
.flatMap(it -> it.getIdProperty())//
|
||||
.map(it -> it.getName()).orElse(ID_FIELD);
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
String idKey = ID_FIELD;
|
||||
if (persistentEntity != null) {
|
||||
if (persistentEntity.getIdProperty() != null) {
|
||||
idKey = persistentEntity.getIdProperty().getName();
|
||||
}
|
||||
}
|
||||
|
||||
return doFindOne(collectionName, new Document(idKey, id), null, entityClass);
|
||||
}
|
||||
@@ -775,11 +766,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
final Document document = query == null ? null
|
||||
Document document = query == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(),
|
||||
Optional.ofNullable(entityClass).flatMap(it -> mappingContext.getPersistentEntity(entityClass)));
|
||||
Optional.ofNullable(entityClass).map(it -> mappingContext.getPersistentEntity(entityClass)));
|
||||
|
||||
return execute(collectionName, (CollectionCallback<Long>) collection -> collection.count(document));
|
||||
return execute(collectionName, collection -> collection.count(document));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -896,13 +887,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
private void initializeVersionProperty(Object entity) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = getPersistentEntity(entity.getClass());
|
||||
MongoPersistentEntity<?> persistentEntity = getPersistentEntity(entity.getClass());
|
||||
|
||||
ifAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty), (l, r) -> {
|
||||
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(l.getPropertyAccessor(entity),
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
|
||||
MongoPersistentProperty versionProperty = persistentEntity.getRequiredVersionProperty();
|
||||
|
||||
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(persistentEntity.getPropertyAccessor(entity),
|
||||
mongoConverter.getConversionService());
|
||||
accessor.setProperty(r, Optional.of(0));
|
||||
});
|
||||
accessor.setProperty(versionProperty, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void insert(Collection<? extends Object> batchToSave, Class<?> entityClass) {
|
||||
@@ -984,12 +978,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.notNull(objectToSave, "Object to save must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(objectToSave.getClass());
|
||||
Optional<MongoPersistentProperty> versionProperty = entity.flatMap(PersistentEntity::getVersionProperty);
|
||||
MongoPersistentEntity<?> entity = getPersistentEntity(objectToSave.getClass());
|
||||
|
||||
mapIfAllPresent(entity, versionProperty, //
|
||||
(l, r) -> doSaveVersioned(objectToSave, l, collectionName))//
|
||||
.orElseGet(() -> doSave(collectionName, objectToSave, this.mongoConverter));
|
||||
if (entity != null && entity.hasVersionProperty()) {
|
||||
doSaveVersioned(objectToSave, entity, collectionName);
|
||||
return;
|
||||
}
|
||||
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
}
|
||||
|
||||
private <T> T doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
|
||||
@@ -997,13 +993,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor(
|
||||
entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService());
|
||||
|
||||
Optional<MongoPersistentProperty> versionProperty = entity.getVersionProperty();
|
||||
Optional<Number> versionNumber = versionProperty.flatMap(it -> convertingAccessor.getProperty(it, Number.class));
|
||||
MongoPersistentProperty property = entity.getRequiredVersionProperty();
|
||||
Number number = convertingAccessor.getProperty(property, Number.class);
|
||||
|
||||
return mapIfAllPresent(versionProperty, versionNumber, (property, number) -> {
|
||||
if (number != null) {
|
||||
|
||||
// Bump version number
|
||||
convertingAccessor.setProperty(property, Optional.of(number.longValue() + 1));
|
||||
convertingAccessor.setProperty(property, number.longValue() + 1);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
@@ -1025,16 +1021,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
if (result.getModifiedCount() == 0) {
|
||||
throw new OptimisticLockingFailureException(
|
||||
String.format("Cannot save entity %s with version %s to collection %s. Has it been modified meanwhile?", id,
|
||||
versionNumber, collectionName));
|
||||
number, collectionName));
|
||||
}
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, document, collectionName));
|
||||
|
||||
return objectToSave;
|
||||
|
||||
}).orElseGet(() -> {
|
||||
doInsert(collectionName, objectToSave, this.mongoConverter);
|
||||
return objectToSave;
|
||||
});
|
||||
}
|
||||
|
||||
doInsert(collectionName, objectToSave, this.mongoConverter);
|
||||
return objectToSave;
|
||||
}
|
||||
|
||||
protected <T> T doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
|
||||
@@ -1188,8 +1184,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
public UpdateResult doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = entityClass == null ? Optional.empty()
|
||||
: getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
@@ -1235,24 +1230,26 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
});
|
||||
}
|
||||
|
||||
private void increaseVersionForUpdateIfNecessary(Optional<? extends MongoPersistentEntity<?>> persistentEntity,
|
||||
Update update) {
|
||||
private void increaseVersionForUpdateIfNecessary(MongoPersistentEntity<?> persistentEntity, Update update) {
|
||||
|
||||
ifAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty),
|
||||
(entity, property) -> {
|
||||
String versionFieldName = property.getFieldName();
|
||||
if (!update.modifies(versionFieldName)) {
|
||||
update.inc(versionFieldName, 1L);
|
||||
}
|
||||
});
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();
|
||||
if (!update.modifies(versionFieldName)) {
|
||||
update.inc(versionFieldName, 1L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean documentContainsVersionProperty(Document document,
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity) {
|
||||
private boolean documentContainsVersionProperty(Document document, MongoPersistentEntity<?> persistentEntity) {
|
||||
|
||||
return mapIfAllPresent(persistentEntity, persistentEntity.flatMap(PersistentEntity::getVersionProperty), //
|
||||
(entity, property) -> document.containsKey(property.getFieldName()))//
|
||||
.orElse(false);
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
|
||||
MongoPersistentProperty property = persistentEntity.getRequiredVersionProperty();
|
||||
|
||||
return document.containsKey(property.getFieldName());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public DeleteResult remove(Object object) {
|
||||
@@ -1282,21 +1279,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
private Pair<String, Optional<Object>> extractIdPropertyAndValue(Object object) {
|
||||
private Pair<String, Object> extractIdPropertyAndValue(Object object) {
|
||||
|
||||
Assert.notNull(object, "Id cannot be extracted from 'null'.");
|
||||
|
||||
Class<?> objectType = object.getClass();
|
||||
|
||||
if (object instanceof Document) {
|
||||
return Pair.of(ID_FIELD, Optional.ofNullable(((Document) object).get(ID_FIELD)));
|
||||
return Pair.of(ID_FIELD, ((Document) object).get(ID_FIELD));
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(objectType);
|
||||
return mapIfAllPresent(entity, entity.flatMap(it -> it.getIdProperty()), //
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
|
||||
|
||||
(l, r) -> Pair.of(r.getFieldName(), l.getPropertyAccessor(object).getProperty(r)))//
|
||||
.orElseThrow(() -> new MappingException("No id property found for object of type " + objectType));
|
||||
if (entity != null && entity.hasIdProperty()) {
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
return Pair.of(idProperty.getFieldName(), entity.getPropertyAccessor(object).getProperty(idProperty));
|
||||
}
|
||||
|
||||
throw new MappingException("No id property found for object of type " + objectType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1307,8 +1308,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
*/
|
||||
private Query getIdQueryFor(Object object) {
|
||||
|
||||
Pair<String, Optional<Object>> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getFirst()).is(id.getSecond().orElse(null)));
|
||||
Pair<String, Object> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getFirst()).is(id.getSecond()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1322,13 +1323,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.notEmpty(objects, "Cannot create Query for empty collection.");
|
||||
|
||||
Iterator<?> it = objects.iterator();
|
||||
Pair<String, Optional<Object>> pair = extractIdPropertyAndValue(it.next());
|
||||
Pair<String, Object> pair = extractIdPropertyAndValue(it.next());
|
||||
|
||||
ArrayList<Object> ids = new ArrayList<Object>(objects.size());
|
||||
ids.add(pair.getSecond().orElse(null));
|
||||
ids.add(pair.getSecond());
|
||||
|
||||
while (it.hasNext()) {
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getSecond().orElse(null));
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getSecond());
|
||||
}
|
||||
|
||||
return new Query(where(pair.getFirst()).in(ids));
|
||||
@@ -1336,15 +1337,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
private void assertUpdateableIdIfNotSet(Object value) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext
|
||||
.getPersistentEntity(value.getClass());
|
||||
Optional<MongoPersistentProperty> idProperty = persistentEntity.flatMap(it -> it.getIdProperty());
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
|
||||
|
||||
Optionals.ifAllPresent(persistentEntity, idProperty, (entity, property) -> {
|
||||
if (entity != null && entity.hasIdProperty()) {
|
||||
|
||||
Optional<Object> propertyValue = entity.getPropertyAccessor(value).getProperty(property);
|
||||
MongoPersistentProperty property = entity.getRequiredIdProperty();
|
||||
Object propertyValue = entity.getPropertyAccessor(value).getProperty(property);
|
||||
|
||||
if (propertyValue.isPresent()) {
|
||||
if (propertyValue != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1353,7 +1353,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!", property.getType().getName(),
|
||||
value.getClass().getName()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public DeleteResult remove(Query query, String collectionName) {
|
||||
@@ -1377,7 +1377,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
final Document queryObject = query.getQueryObject();
|
||||
final Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(entityClass);
|
||||
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
return execute(collectionName, new CollectionCallback<DeleteResult>() {
|
||||
|
||||
@@ -1948,7 +1948,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
*/
|
||||
protected <T> T doFindOne(String collectionName, Document query, Document fields, Class<T> entityClass) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
|
||||
|
||||
@@ -1998,7 +1998,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
protected <S, T> List<T> doFind(String collectionName, Document query, Document fields, Class<S> entityClass,
|
||||
CursorPreparer preparer, DocumentCallback<T> objectCallback) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
Document mappedFields = queryMapper.getMappedFields(fields, entity);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
@@ -2069,7 +2069,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
serializeToJsonSafely(query), fields, sort, entityClass, collectionName);
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
return executeFindOneInternal(
|
||||
new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort, collation),
|
||||
@@ -2085,7 +2085,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
options = new FindAndModifyOptions();
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
@@ -2121,17 +2121,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
return;
|
||||
}
|
||||
|
||||
getIdPropertyFor(savedObject.getClass()).ifPresent(idProp -> {
|
||||
MongoPersistentProperty idProperty = getIdPropertyFor(savedObject.getClass());
|
||||
|
||||
if (idProperty != null) {
|
||||
|
||||
ConversionService conversionService = mongoConverter.getConversionService();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(savedObject.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
|
||||
|
||||
Optional<Object> value = accessor.getProperty(idProp);
|
||||
if (!value.isPresent()) {
|
||||
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, Optional.of(id));
|
||||
Object value = accessor.getProperty(idProperty);
|
||||
if (value == null) {
|
||||
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProperty, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private MongoCollection<Document> getAndPrepareCollection(MongoDatabase db, String collectionName) {
|
||||
@@ -2262,12 +2264,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
return exceptionTranslator;
|
||||
}
|
||||
|
||||
private Optional<? extends MongoPersistentEntity<?>> getPersistentEntity(Class<?> type) {
|
||||
return Optional.ofNullable(type).flatMap(mappingContext::getPersistentEntity);
|
||||
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
|
||||
return type != null ? mappingContext.getPersistentEntity(type) : null;
|
||||
}
|
||||
|
||||
private Optional<MongoPersistentProperty> getIdPropertyFor(Class<?> type) {
|
||||
return mappingContext.getPersistentEntity(type).flatMap(PersistentEntity::getIdProperty);
|
||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = getPersistentEntity(type);
|
||||
return persistentEntity != null ? persistentEntity.getIdProperty() : null;
|
||||
}
|
||||
|
||||
private <T> String determineEntityCollectionName(T obj) {
|
||||
|
||||
@@ -22,17 +22,8 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -59,11 +50,10 @@ import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.convert.DbRefProxyHandler;
|
||||
@@ -94,6 +84,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -615,8 +606,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
*/
|
||||
public <T> Mono<T> findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity.flatMap(PersistentEntity::getIdProperty).orElse(null);
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity != null ? persistentEntity.getIdProperty() : null;
|
||||
|
||||
String idKey = idProperty == null ? ID_FIELD : idProperty.getName();
|
||||
|
||||
@@ -764,7 +755,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
|
||||
final Document Document = query == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? Optional.empty() : mappingContext.getPersistentEntity(entityClass));
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
|
||||
return collection.count(Document);
|
||||
});
|
||||
@@ -971,29 +962,28 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor(
|
||||
entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService());
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty()
|
||||
.orElseThrow(() -> new IllegalArgumentException("No id property present!"));
|
||||
MongoPersistentProperty versionProperty = entity.getVersionProperty()
|
||||
.orElseThrow(() -> new IllegalArgumentException("No version property present!"));
|
||||
;
|
||||
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
|
||||
MongoPersistentProperty versionProperty = entity.getRequiredVersionProperty();
|
||||
|
||||
Optional<Object> version = convertingAccessor.getProperty(versionProperty);
|
||||
Optional<Number> versionNumber = convertingAccessor.getProperty(versionProperty, Number.class);
|
||||
Object version = convertingAccessor.getProperty(versionProperty);
|
||||
Number versionNumber = convertingAccessor.getProperty(versionProperty, Number.class);
|
||||
|
||||
// Fresh instance -> initialize version property
|
||||
if (!version.isPresent()) {
|
||||
if (version == null) {
|
||||
return doInsert(collectionName, objectToSave, mongoConverter);
|
||||
}
|
||||
|
||||
ReactiveMongoTemplate.this.assertUpdateableIdIfNotSet(objectToSave);
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
// Create query for entity with the id and old version
|
||||
Optional<Object> id = convertingAccessor.getProperty(idProperty);
|
||||
Query query = new Query(
|
||||
Criteria.where(idProperty.getName()).is(id.get()).and(versionProperty.getName()).is(version.get()));
|
||||
Object id = convertingAccessor.getProperty(idProperty);
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
|
||||
|
||||
if (versionNumber == null) {
|
||||
versionNumber = 0;
|
||||
}
|
||||
// Bump version number
|
||||
convertingAccessor.setProperty(versionProperty, Optional.of(versionNumber.orElse(0).longValue() + 1));
|
||||
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
|
||||
|
||||
ReactiveMongoTemplate.this.maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
|
||||
@@ -1241,7 +1231,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
private void increaseVersionForUpdateIfNecessary(MongoPersistentEntity<?> persistentEntity, Update update) {
|
||||
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
String versionFieldName = persistentEntity.getVersionProperty().get().getFieldName();
|
||||
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();
|
||||
if (!update.modifies(versionFieldName)) {
|
||||
update.inc(versionFieldName, 1L);
|
||||
}
|
||||
@@ -1254,7 +1244,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
return false;
|
||||
}
|
||||
|
||||
return document.containsKey(persistentEntity.getVersionProperty().get().getFieldName());
|
||||
return document.containsKey(persistentEntity.getRequiredIdProperty().getFieldName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -1306,25 +1296,27 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
private Entry<String, Object> extractIdPropertyAndValue(Object object) {
|
||||
private Pair<String, Object> extractIdPropertyAndValue(Object object) {
|
||||
|
||||
Assert.notNull(object, "Id cannot be extracted from 'null'.");
|
||||
|
||||
Assert.notNull(object, "Id cannot be extracted from 'null'.");
|
||||
|
||||
Class<?> objectType = object.getClass();
|
||||
|
||||
if (object instanceof Document) {
|
||||
return Collections.singletonMap(ID_FIELD, ((Document) object).get(ID_FIELD)).entrySet().iterator().next();
|
||||
return Pair.of(ID_FIELD, ((Document) object).get(ID_FIELD));
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(objectType);
|
||||
MongoPersistentProperty idProp = entity.flatMap(PersistentEntity::getIdProperty).orElse(null);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
|
||||
|
||||
if (idProp == null) {
|
||||
throw new MappingException("No id property found for object of type " + objectType);
|
||||
if (entity != null && entity.hasIdProperty()) {
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
return Pair.of(idProperty.getFieldName(), entity.getPropertyAccessor(object).getProperty(idProperty));
|
||||
}
|
||||
|
||||
Optional<Object> idValue = entity.get().getPropertyAccessor(object).getProperty(idProp);
|
||||
return Collections.singletonMap(idProp.getFieldName(), idValue.get()).entrySet().iterator().next();
|
||||
throw new MappingException("No id property found for object of type " + objectType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1335,8 +1327,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
*/
|
||||
private Query getIdQueryFor(Object object) {
|
||||
|
||||
Entry<String, Object> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getKey()).is(id.getValue()));
|
||||
Pair<String, Object> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getFirst()).is(id.getSecond()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1350,35 +1342,36 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
Assert.notEmpty(objects, "Cannot create Query for empty collection.");
|
||||
|
||||
Iterator<?> it = objects.iterator();
|
||||
Entry<String, Object> firstEntry = extractIdPropertyAndValue(it.next());
|
||||
Pair<String, Object> firstEntry = extractIdPropertyAndValue(it.next());
|
||||
|
||||
ArrayList<Object> ids = new ArrayList<Object>(objects.size());
|
||||
ids.add(firstEntry.getValue());
|
||||
ids.add(firstEntry.getSecond());
|
||||
|
||||
while (it.hasNext()) {
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getValue());
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getSecond());
|
||||
}
|
||||
|
||||
return new Query(where(firstEntry.getKey()).in(ids));
|
||||
return new Query(where(firstEntry.getFirst()).in(ids));
|
||||
}
|
||||
|
||||
private void assertUpdateableIdIfNotSet(Object entity) {
|
||||
private void assertUpdateableIdIfNotSet(Object value) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext
|
||||
.getPersistentEntity(entity.getClass());
|
||||
Optional<MongoPersistentProperty> idProperty = persistentEntity.isPresent() ? persistentEntity.get().getIdProperty()
|
||||
: Optional.empty();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
|
||||
|
||||
if (!idProperty.isPresent()) {
|
||||
return;
|
||||
}
|
||||
if (entity != null && entity.hasIdProperty()) {
|
||||
|
||||
Optional<Object> idValue = persistentEntity.get().getPropertyAccessor(entity).getProperty(idProperty.get());
|
||||
MongoPersistentProperty property = entity.getRequiredIdProperty();
|
||||
Object propertyValue = entity.getPropertyAccessor(value).getProperty(property);
|
||||
|
||||
if (!idValue.isPresent() && !MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(idProperty.get().getType())) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!",
|
||||
idProperty.get().getType().getName(), entity.getClass().getName()));
|
||||
if (propertyValue != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(property.getType())) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!", property.getType().getName(),
|
||||
value.getClass().getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1557,7 +1550,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
protected <T> Mono<T> doFindOne(String collectionName, Document query, Document fields, Class<T> entityClass,
|
||||
Collation collation) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
|
||||
|
||||
@@ -1607,7 +1600,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
protected <S, T> Flux<T> doFind(String collectionName, Document query, Document fields, Class<S> entityClass,
|
||||
FindPublisherPreparer preparer, DocumentCallback<T> objectCallback) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
Document mappedFields = queryMapper.getMappedFields(fields, entity);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
@@ -1654,7 +1647,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
serializeToJsonSafely(query), fields, sort, entityClass, collectionName));
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
return executeFindOneInternal(
|
||||
new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort, collation),
|
||||
@@ -1666,11 +1659,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
|
||||
FindAndModifyOptions optionsToUse = options != null ? options : new FindAndModifyOptions();
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
return Mono.defer(() -> {
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity.get(), update);
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
Document mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
|
||||
@@ -1721,11 +1714,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(savedObject.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
|
||||
|
||||
if (accessor.getProperty(idProp).isPresent()) {
|
||||
if (accessor.getProperty(idProp) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, Optional.ofNullable(id));
|
||||
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, id);
|
||||
}
|
||||
|
||||
private MongoCollection<Document> getAndPrepareCollection(MongoDatabase db, String collectionName) {
|
||||
@@ -1896,13 +1889,13 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
}
|
||||
|
||||
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
|
||||
return type == null ? null : mappingContext.getPersistentEntity(type).orElse(null);
|
||||
return type == null ? null : mappingContext.getPersistentEntity(type);
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext.getPersistentEntity(type);
|
||||
return persistentEntity.flatMap(PersistentEntity::getIdProperty).orElse(null);
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(type);
|
||||
return persistentEntity != null ? persistentEntity.getIdProperty() : null;
|
||||
}
|
||||
|
||||
private <T> String determineEntityCollectionName(T obj) {
|
||||
@@ -1976,7 +1969,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
if (mongoPersistentEntity != null && mongoPersistentEntity.hasVersionProperty()) {
|
||||
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(
|
||||
mongoPersistentEntity.getPropertyAccessor(entity), mongoConverter.getConversionService());
|
||||
accessor.setProperty(mongoPersistentEntity.getVersionProperty().get(), Optional.of(0));
|
||||
accessor.setProperty(mongoPersistentEntity.getRequiredVersionProperty(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,9 +2342,9 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
|
||||
static class NoOpDbRefResolver implements DbRefResolver {
|
||||
|
||||
@Override
|
||||
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
DbRefProxyHandler proxyHandler) {
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.bson.Document;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
@@ -27,7 +26,7 @@ import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Used to resolve associations annotated with {@link org.springframework.data.mongodb.core.mapping.DBRef}.
|
||||
*
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
@@ -40,19 +39,19 @@ public interface DbRefResolver {
|
||||
* Resolves the given {@link DBRef} into an object of the given {@link MongoPersistentProperty}'s type. The method
|
||||
* might return a proxy object for the {@link DBRef} or resolve it immediately. In both cases the
|
||||
* {@link DbRefResolverCallback} will be used to obtain the actual backing object.
|
||||
*
|
||||
*
|
||||
* @param property will never be {@literal null}.
|
||||
* @param dbref the {@link DBRef} to resolve.
|
||||
* @param callback will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
DbRefProxyHandler proxyHandler);
|
||||
|
||||
/**
|
||||
* Creates a {@link DBRef} instance for the given {@link org.springframework.data.mongodb.core.mapping.DBRef}
|
||||
* annotation, {@link MongoPersistentEntity} and id.
|
||||
*
|
||||
*
|
||||
* @param annotation will never be {@literal null}.
|
||||
* @param entity will never be {@literal null}.
|
||||
* @param id will never be {@literal null}.
|
||||
@@ -63,7 +62,7 @@ public interface DbRefResolver {
|
||||
|
||||
/**
|
||||
* Actually loads the {@link DBRef} from the datasource.
|
||||
*
|
||||
*
|
||||
* @param dbRef must not be {@literal null}.
|
||||
* @return
|
||||
* @since 1.7
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ import com.mongodb.DBRef;
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class DefaultDbRefProxyHandler implements DbRefProxyHandler {
|
||||
|
||||
@@ -50,7 +51,7 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.DbRefProxyHandler#populateId(com.mongodb.DBRef, java.lang.Object)
|
||||
*/
|
||||
@@ -62,8 +63,7 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(property);
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty()
|
||||
.orElseThrow(() -> new IllegalStateException("Couldn't find identifier property!"));
|
||||
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
|
||||
|
||||
if (idProperty.usePropertyAccess()) {
|
||||
return proxy;
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -55,7 +54,7 @@ import com.mongodb.client.model.Filters;
|
||||
/**
|
||||
* A {@link DbRefResolver} that resolves {@link org.springframework.data.mongodb.core.mapping.DBRef}s by delegating to a
|
||||
* {@link DbRefResolverCallback} than is able to generate lazy loading proxies.
|
||||
*
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
@@ -70,7 +69,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}.
|
||||
*
|
||||
*
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
*/
|
||||
public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) {
|
||||
@@ -87,20 +86,20 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#resolveDbRef(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.convert.DbRefResolverCallback)
|
||||
*/
|
||||
@Override
|
||||
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
DbRefProxyHandler handler) {
|
||||
|
||||
Assert.notNull(property, "Property must not be null!");
|
||||
Assert.notNull(callback, "Callback must not be null!");
|
||||
|
||||
if (isLazyDbRef(property)) {
|
||||
return Optional.of(createLazyLoadingProxy(property, dbref, callback, handler));
|
||||
return createLazyLoadingProxy(property, dbref, callback, handler);
|
||||
}
|
||||
|
||||
return Optional.ofNullable(callback.resolve(property));
|
||||
return callback.resolve(property);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#created(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.mapping.MongoPersistentEntity, java.lang.Object)
|
||||
*/
|
||||
@@ -165,7 +164,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
/**
|
||||
* Creates a proxy for the given {@link MongoPersistentProperty} using the given {@link DbRefResolverCallback} to
|
||||
* eventually resolve the value of the property.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @param dbref can be {@literal null}.
|
||||
* @param callback must not be {@literal null}.
|
||||
@@ -200,7 +199,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Returns the CGLib enhanced type for the given source type.
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
@@ -216,7 +215,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Returns whether the property shall be resolved lazily.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -228,7 +227,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
* A {@link MethodInterceptor} that is used within a lazy loading proxy. The property resolving is delegated to a
|
||||
* {@link DbRefResolverCallback}. The resolving process is triggered by a method invocation on the proxy and is
|
||||
* guaranteed to be performed only once.
|
||||
*
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
@@ -259,7 +258,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
/**
|
||||
* Creates a new {@link LazyLoadingInterceptor} for the given {@link MongoPersistentProperty},
|
||||
* {@link PersistenceExceptionTranslator} and {@link DbRefResolverCallback}.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @param dbref can be {@literal null}.
|
||||
* @param callback must not be {@literal null}.
|
||||
@@ -286,7 +285,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.springframework.cglib.proxy.MethodProxy)
|
||||
*/
|
||||
@@ -332,7 +331,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Returns a to string representation for the given {@code proxy}.
|
||||
*
|
||||
*
|
||||
* @param proxy
|
||||
* @return
|
||||
*/
|
||||
@@ -353,7 +352,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Returns the hashcode for the given {@code proxy}.
|
||||
*
|
||||
*
|
||||
* @param proxy
|
||||
* @return
|
||||
*/
|
||||
@@ -363,7 +362,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Performs an equality check for the given {@code proxy}.
|
||||
*
|
||||
*
|
||||
* @param proxy
|
||||
* @param that
|
||||
* @return
|
||||
@@ -383,7 +382,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Will trigger the resolution if the proxy is not resolved already or return a previously resolved result.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Object ensureResolved() {
|
||||
@@ -398,7 +397,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Callback method for serialization.
|
||||
*
|
||||
*
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
@@ -410,7 +409,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Callback method for deserialization.
|
||||
*
|
||||
*
|
||||
* @param in
|
||||
* @throws IOException
|
||||
*/
|
||||
@@ -426,7 +425,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
||||
|
||||
/**
|
||||
* Resolves the proxy into its backing object.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private synchronized Object resolve() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,9 +22,10 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link DbRefResolverCallback}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class DefaultDbRefResolverCallback implements DbRefResolverCallback {
|
||||
|
||||
@@ -36,7 +37,7 @@ class DefaultDbRefResolverCallback implements DbRefResolverCallback {
|
||||
/**
|
||||
* Creates a new {@link DefaultDbRefResolverCallback} using the given {@link Document}, {@link ObjectPath},
|
||||
* {@link ValueResolver} and {@link SpELExpressionEvaluator}.
|
||||
*
|
||||
*
|
||||
* @param surroundingObject must not be {@literal null}.
|
||||
* @param path must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
@@ -51,12 +52,12 @@ class DefaultDbRefResolverCallback implements DbRefResolverCallback {
|
||||
this.evaluator = evaluator;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.DbRefResolverCallback#resolve(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty)
|
||||
*/
|
||||
@Override
|
||||
public Object resolve(MongoPersistentProperty property) {
|
||||
return resolver.getValueInternal(property, surroundingObject, evaluator, path).orElse(null);
|
||||
return resolver.getValueInternal(property, surroundingObject, evaluator, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,17 +32,17 @@ import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
|
||||
* information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
|
||||
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
|
||||
* respectively.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
@@ -94,7 +94,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
|
||||
return typeKey == null ? false : typeKey.equals(key);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#writeTypeRestrictions(java.util.Set)
|
||||
*/
|
||||
@@ -111,26 +111,26 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
|
||||
|
||||
Alias typeAlias = getAliasFor(ClassTypeInformation.from(restrictedType));
|
||||
|
||||
if (typeAlias != null && !ObjectUtils.nullSafeEquals(Alias.NONE, typeAlias) && typeAlias.getValue().isPresent()) {
|
||||
restrictedMappedTypes.add(typeAlias.getValue().get());
|
||||
if (typeAlias != null && !ObjectUtils.nullSafeEquals(Alias.NONE, typeAlias) && typeAlias.isPresent()) {
|
||||
restrictedMappedTypes.add(typeAlias.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
accessor.writeTypeTo(result, new Document("$in", restrictedMappedTypes));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Optional<TypeInformation<?>> getFallbackTypeFor(Bson source) {
|
||||
return Optional.of(source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO);
|
||||
protected TypeInformation<?> getFallbackTypeFor(Bson source) {
|
||||
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypeAliasAccessor} to store aliases in a {@link Document}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static final class DocumentTypeAliasAccessor implements TypeAliasAccessor<Bson> {
|
||||
@@ -152,9 +152,9 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
|
||||
}
|
||||
|
||||
if (source instanceof Document) {
|
||||
return Alias.ofOptional(Optional.ofNullable(((Document) source).get(typeKey)));
|
||||
return Alias.ofNullable(((Document) source).get(typeKey));
|
||||
} else if (source instanceof DBObject) {
|
||||
return Alias.ofOptional(Optional.ofNullable(((DBObject) source).get(typeKey)));
|
||||
return Alias.ofNullable(((DBObject) source).get(typeKey));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot read alias from " + source.getClass());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,6 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
@@ -34,9 +32,10 @@ import com.mongodb.DBObject;
|
||||
* Wrapper value object for a {@link Document} to be able to access raw values by {@link MongoPersistentProperty}
|
||||
* references. The accessors will transparently resolve nested document values that a {@link MongoPersistentProperty}
|
||||
* might refer to through a path expression in field names.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class DocumentAccessor {
|
||||
|
||||
@@ -44,7 +43,7 @@ class DocumentAccessor {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DocumentAccessor} for the given {@link Document}.
|
||||
*
|
||||
*
|
||||
* @param document must be a {@link Document} effectively, must not be {@literal null}.
|
||||
*/
|
||||
public DocumentAccessor(Bson document) {
|
||||
@@ -62,7 +61,7 @@ class DocumentAccessor {
|
||||
* Puts the given value into the backing {@link Document} based on the coordinates defined through the given
|
||||
* {@link MongoPersistentProperty}. By default this will be the plain field name. But field names might also consist
|
||||
* of path traversals so we might need to create intermediate {@link BasicDocument}s.
|
||||
*
|
||||
*
|
||||
* @param prop must not be {@literal null}.
|
||||
* @param value
|
||||
*/
|
||||
@@ -91,20 +90,11 @@ class DocumentAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
public void computeIfAbsent(MongoPersistentProperty prop, Supplier<Optional<Object>> supplier) {
|
||||
|
||||
if (hasValue(prop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
supplier.get().ifPresent(it -> put(prop, it));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value the given {@link MongoPersistentProperty} refers to. By default this will be a direct field but
|
||||
* the method will also transparently resolve nested values the {@link MongoPersistentProperty} might refer to through
|
||||
* a path expression in the field name metadata.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -161,7 +151,7 @@ class DocumentAccessor {
|
||||
|
||||
if (this.document instanceof Document) {
|
||||
source = ((Document) this.document);
|
||||
}else {
|
||||
} else {
|
||||
source = ((DBObject) this.document).toMap();
|
||||
}
|
||||
|
||||
@@ -182,7 +172,7 @@ class DocumentAccessor {
|
||||
|
||||
/**
|
||||
* Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise.
|
||||
*
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -207,7 +197,7 @@ class DocumentAccessor {
|
||||
/**
|
||||
* Returns the {@link Document} which either already exists in the given source under the given key, or creates a new
|
||||
* nested one, registers it with the source and returns it.
|
||||
*
|
||||
*
|
||||
* @param key must not be {@literal null} or empty.
|
||||
* @param source must not be {@literal null}.
|
||||
* @return
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
@@ -30,14 +39,14 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
@@ -52,7 +61,6 @@ import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -82,9 +90,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(MappingMongoConverter.class);
|
||||
|
||||
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
protected final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
protected final QueryMapper idMapper;
|
||||
protected final DbRefResolver dbRefResolver;
|
||||
protected final DefaultDbRefProxyHandler dbRefProxyHandler;
|
||||
|
||||
protected ApplicationContext applicationContext;
|
||||
protected MongoTypeMapper typeMapper;
|
||||
@@ -112,6 +120,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
this.idMapper = new QueryMapper(this);
|
||||
|
||||
this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
|
||||
this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,66 +257,89 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final Document bson, final ObjectPath path) {
|
||||
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
|
||||
DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
|
||||
|
||||
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, bson, evaluator, path);
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, provider);
|
||||
|
||||
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
|
||||
PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
|
||||
conversionService);
|
||||
|
||||
final Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
final S result = instance;
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
DocumentAccessor documentAccessor = new DocumentAccessor(bson);
|
||||
|
||||
// make sure id property is set before all other properties
|
||||
Optional<Object> idValue = idProperty.filter(documentAccessor::hasValue).map(it -> {
|
||||
Object idValue = null;
|
||||
|
||||
Optional<Object> value = getValueInternal(it, bson, evaluator, path);
|
||||
accessor.setProperty(it, value);
|
||||
if (idProperty != null && documentAccessor.hasValue(idProperty)) {
|
||||
|
||||
return value;
|
||||
});
|
||||
idValue = readIdValue(path, evaluator, idProperty, documentAccessor);
|
||||
accessor.setProperty(idProperty, idValue);
|
||||
}
|
||||
|
||||
final ObjectPath currentPath = path.push(result, entity,
|
||||
idValue.isPresent() ? idProperty.map(it -> bson.get(it.getFieldName())).orElse(null) : null);
|
||||
ObjectPath currentPath = path.push(instance, entity, idValue != null ? bson.get(idProperty.getFieldName()) : null);
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties((PropertyHandler<MongoPersistentProperty>) prop -> {
|
||||
MongoDbPropertyValueProvider valueProvider = new MongoDbPropertyValueProvider(documentAccessor, evaluator,
|
||||
currentPath);
|
||||
|
||||
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(bson, currentPath, evaluator,
|
||||
MappingMongoConverter.this);
|
||||
readProperties(entity, accessor, idProperty, documentAccessor, valueProvider, callback);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Object readIdValue(ObjectPath path, DefaultSpELExpressionEvaluator evaluator,
|
||||
MongoPersistentProperty idProperty, DocumentAccessor documentAccessor) {
|
||||
|
||||
String expression = idProperty.getSpelExpression();
|
||||
Object resolvedValue = expression != null ? evaluator.evaluate(expression) : documentAccessor.get(idProperty);
|
||||
|
||||
return resolvedValue != null ? readValue(resolvedValue, idProperty.getTypeInformation(), path) : null;
|
||||
}
|
||||
|
||||
private void readProperties(MongoPersistentEntity<?> entity, PersistentPropertyAccessor accessor,
|
||||
MongoPersistentProperty idProperty, DocumentAccessor documentAccessor,
|
||||
MongoDbPropertyValueProvider valueProvider, DbRefResolverCallback callback) {
|
||||
|
||||
|
||||
for (MongoPersistentProperty prop : entity) {
|
||||
|
||||
if(prop.isAssociation() && !entity.isConstructorArgument(prop)) {
|
||||
readAssociation(prop.getAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback );
|
||||
continue;
|
||||
}
|
||||
// we skip the id property since it was already set
|
||||
if (idProperty != null && idProperty.equals(prop)) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity.isConstructorArgument(prop) || !documentAccessor.hasValue(prop)) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
accessor.setProperty(prop, getValueInternal(prop, bson, evaluator, currentPath));
|
||||
});
|
||||
if(prop.isAssociation()) {
|
||||
readAssociation(prop.getAssociation(), accessor, documentAccessor, dbRefProxyHandler, callback );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle associations
|
||||
entity.doWithAssociations((AssociationHandler<MongoPersistentProperty>) association -> {
|
||||
accessor.setProperty(prop, valueProvider.getPropertyValue(prop));
|
||||
}
|
||||
}
|
||||
|
||||
final MongoPersistentProperty property = association.getInverse();
|
||||
private void readAssociation(Association<MongoPersistentProperty> association, PersistentPropertyAccessor accessor,
|
||||
DocumentAccessor documentAccessor, DbRefProxyHandler handler, DbRefResolverCallback callback) {
|
||||
|
||||
MongoPersistentProperty property = association.getInverse();
|
||||
Object value = documentAccessor.get(property);
|
||||
|
||||
if (value == null || entity.isConstructorArgument(property)) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBRef dbref = value instanceof DBRef ? (DBRef) value : null;
|
||||
|
||||
DbRefProxyHandler handler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this);
|
||||
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(bson, currentPath, evaluator,
|
||||
MappingMongoConverter.this);
|
||||
|
||||
accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler));
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -348,8 +380,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;
|
||||
|
||||
writeInternal(target, bson, Optional.of(type));
|
||||
if (asMap(bson).containsKey("_is") && asMap(bson).get("_id") == null) {
|
||||
writeInternal(target, bson, type);
|
||||
if (asMap(bson).containsKey("_id") && asMap(bson).get("_id") == null) {
|
||||
removeFromMap(bson, "_id");
|
||||
}
|
||||
|
||||
@@ -366,7 +398,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param bson
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeInternal(final Object obj, final Bson bson, final Optional<TypeInformation<?>> typeHint) {
|
||||
protected void writeInternal(final Object obj, final Bson bson, final TypeInformation<?> typeHint) {
|
||||
|
||||
if (null == obj) {
|
||||
return;
|
||||
@@ -387,7 +419,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(entityType)) {
|
||||
writeCollectionInternal((Collection<?>) obj, Optional.of(ClassTypeInformation.LIST), (BasicDBList) bson);
|
||||
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) bson);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -406,46 +438,65 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
throw new MappingException("No mapping metadata found for entity of type " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
|
||||
DocumentAccessor dbObjectAccessor = new DocumentAccessor(bson);
|
||||
|
||||
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
idProperty.ifPresent(
|
||||
prop -> dbObjectAccessor.computeIfAbsent(prop, () -> idMapper.convertId(accessor.getProperty(prop))));
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
if (idProperty != null && !dbObjectAccessor.hasValue(idProperty)) {
|
||||
|
||||
Object value = idMapper.convertId(accessor.getProperty(idProperty));
|
||||
|
||||
if (value != null) {
|
||||
dbObjectAccessor.put(idProperty, value);
|
||||
}
|
||||
}
|
||||
writeProperties(bson, entity, accessor, dbObjectAccessor, idProperty);
|
||||
}
|
||||
|
||||
private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, PersistentPropertyAccessor accessor,
|
||||
DocumentAccessor dbObjectAccessor, MongoPersistentProperty idProperty) {
|
||||
|
||||
// Write the properties
|
||||
entity.doWithProperties((PropertyHandler<MongoPersistentProperty>) prop -> {
|
||||
for (MongoPersistentProperty prop : entity) {
|
||||
|
||||
if (idProperty.map(it -> it.equals(prop)).orElse(false) || !prop.isWritable()) {
|
||||
return;
|
||||
|
||||
if (prop.equals(idProperty) || !prop.isWritable()) {
|
||||
continue;
|
||||
}
|
||||
if(prop.isAssociation()) {
|
||||
writeAssociation(prop.getAssociation(), accessor, dbObjectAccessor);
|
||||
continue;
|
||||
}
|
||||
|
||||
accessor.getProperty(prop).ifPresent(it -> {
|
||||
if (!conversions.isSimpleType(it.getClass())) {
|
||||
Object value = accessor.getProperty(prop);
|
||||
|
||||
writePropertyInternal(it, bson, prop);
|
||||
} else {
|
||||
writeSimpleInternal(it, bson, prop);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entity.doWithAssociations((AssociationHandler<MongoPersistentProperty>) association -> {
|
||||
if (!conversions.isSimpleType(value.getClass())) {
|
||||
writePropertyInternal(value, dbObjectAccessor, prop);
|
||||
} else {
|
||||
writeSimpleInternal(value, bson, prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAssociation(Association<MongoPersistentProperty> association, PersistentPropertyAccessor accessor,
|
||||
DocumentAccessor dbObjectAccessor) {
|
||||
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
accessor.getProperty(inverseProp).ifPresent(it -> writePropertyInternal(it, bson, inverseProp));
|
||||
});
|
||||
|
||||
writePropertyInternal(accessor.getProperty(inverseProp), dbObjectAccessor, inverseProp);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected void writePropertyInternal(Object obj, Bson bson, MongoPersistentProperty prop) {
|
||||
protected void writePropertyInternal(Object obj, DocumentAccessor accessor, MongoPersistentProperty prop) {
|
||||
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DocumentAccessor accessor = new DocumentAccessor(bson);
|
||||
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
@@ -497,14 +548,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return;
|
||||
}
|
||||
|
||||
Object existingValue = accessor.get(prop);
|
||||
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
|
||||
|
||||
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
|
||||
? mappingContext.getRequiredPersistentEntity(obj.getClass()) : mappingContext.getRequiredPersistentEntity(type);
|
||||
|
||||
Object existingValue = accessor.get(prop);
|
||||
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
|
||||
|
||||
writeInternal(obj, document, entity);
|
||||
addCustomTypeKeyIfNecessary(Optional.of(ClassTypeInformation.from(prop.getRawType())), obj, document);
|
||||
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, document);
|
||||
accessor.put(prop, document);
|
||||
}
|
||||
|
||||
@@ -539,7 +590,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
protected List<Object> createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
||||
|
||||
if (!property.isDbReference()) {
|
||||
return writeCollectionInternal(collection, Optional.of(property.getTypeInformation()), new BasicDBList());
|
||||
return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList());
|
||||
}
|
||||
|
||||
List<Object> dbList = new ArrayList<>(collection.size());
|
||||
@@ -601,10 +652,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param sink the {@link BasicDBList} to write to.
|
||||
* @return
|
||||
*/
|
||||
private BasicDBList writeCollectionInternal(Collection<?> source, Optional<TypeInformation<?>> type,
|
||||
BasicDBList sink) {
|
||||
private BasicDBList writeCollectionInternal(Collection<?> source, TypeInformation<?> type, BasicDBList sink) {
|
||||
|
||||
Optional<TypeInformation<?>> componentType = type.flatMap(TypeInformation::getComponentType);
|
||||
TypeInformation<?> componentType = null;
|
||||
|
||||
if (type != null) {
|
||||
componentType = type.getComponentType();
|
||||
}
|
||||
|
||||
for (Object element : source) {
|
||||
|
||||
@@ -649,8 +703,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
|
||||
} else {
|
||||
Document document = new Document();
|
||||
Optional<TypeInformation<?>> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: Optional.of(ClassTypeInformation.OBJECT);
|
||||
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: ClassTypeInformation.OBJECT;
|
||||
writeInternal(val, document, valueTypeInfo);
|
||||
addToMap(bson, simpleKey, document);
|
||||
}
|
||||
@@ -736,10 +790,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param value must not be {@literal null}.
|
||||
* @param bson must not be {@literal null}.
|
||||
*/
|
||||
protected void addCustomTypeKeyIfNecessary(Optional<TypeInformation<?>> type, Object value, Bson bson) {
|
||||
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, Bson bson) {
|
||||
|
||||
Optional<Class<?>> actualType = type.map(TypeInformation::getActualType).map(TypeInformation::getType);
|
||||
Class<?> reference = actualType.orElse(Object.class);
|
||||
Class<?> reference = type != null ? type.getActualType().getType() : Object.class;
|
||||
Class<?> valueType = ClassUtils.getUserClass(value.getClass());
|
||||
|
||||
boolean notTheSameClass = !valueType.equals(reference);
|
||||
@@ -779,18 +832,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Optional<Class<?>> customTarget = conversions.getCustomWriteTarget(value.getClass());
|
||||
|
||||
return customTarget.map(it -> (Object) conversionService.convert(value, it)).orElseGet(() -> {
|
||||
if (customTarget.isPresent()) {
|
||||
return conversionService.convert(value, customTarget.get());
|
||||
}
|
||||
|
||||
if (ObjectUtils.isArray(value)) {
|
||||
if (ObjectUtils.isArray(value)) {
|
||||
|
||||
if (value instanceof byte[]) {
|
||||
return value;
|
||||
}
|
||||
return asCollection(value);
|
||||
if (value instanceof byte[]) {
|
||||
return value;
|
||||
}
|
||||
return asCollection(value);
|
||||
}
|
||||
|
||||
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
|
||||
});
|
||||
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,30 +881,30 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return (DBRef) target;
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
targetEntity = targetEntity.isPresent() ? targetEntity : mappingContext.getPersistentEntity(property);
|
||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
targetEntity = targetEntity != null ? targetEntity : mappingContext.getPersistentEntity(property);
|
||||
|
||||
if (null == targetEntity) {
|
||||
throw new MappingException("No mapping metadata found for " + target.getClass());
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = targetEntity
|
||||
.orElseThrow(() -> new MappingException("No mapping metadata found for " + target.getClass()));
|
||||
MongoPersistentEntity<?> entity = targetEntity;
|
||||
|
||||
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
return idProperty.map(it -> {
|
||||
if (idProperty != null) {
|
||||
|
||||
Object id = target.getClass().equals(it.getType()) ? target : entity.getPropertyAccessor(target).getProperty(it);
|
||||
Object id = target.getClass().equals(idProperty.getType()) ? target
|
||||
: entity.getPropertyAccessor(target).getProperty(idProperty);
|
||||
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
|
||||
return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity,
|
||||
idMapper.convertId(id instanceof Optional ? (Optional) id : Optional.ofNullable(id)).orElse(null));
|
||||
return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity, idMapper.convertId(id));
|
||||
}
|
||||
|
||||
}).orElseThrow(() -> new MappingException("No id property found on class " + entity.getType()));
|
||||
throw new MappingException("No id property found on class " + entity.getType());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -858,7 +912,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
ObjectPath path) {
|
||||
return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop);
|
||||
}
|
||||
@@ -879,7 +933,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
|
||||
TypeInformation<?> componentType = targetType.getComponentType().orElse(ClassTypeInformation.OBJECT);
|
||||
TypeInformation<?> componentType = targetType.getComponentType() != null ? targetType.getComponentType()
|
||||
: ClassTypeInformation.OBJECT;
|
||||
Class<?> rawComponentType = componentType.getType();
|
||||
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
@@ -941,15 +996,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Class<?> mapType = typeMapper.readType(bson, type).getType();
|
||||
|
||||
Optional<TypeInformation<?>> valueType = type.getMapValueType();
|
||||
Class<?> rawKeyType = type.getComponentType().map(TypeInformation::getType).orElse(null);
|
||||
Class<?> rawValueType = type.getMapValueType().map(TypeInformation::getType).orElse(null);
|
||||
TypeInformation<?> keyType = type.getComponentType();
|
||||
TypeInformation<?> valueType = type.getMapValueType();
|
||||
|
||||
Class<?> rawKeyType = keyType != null ? keyType.getType() : null;
|
||||
Class<?> rawValueType = valueType != null ? valueType.getType() : null;
|
||||
|
||||
Map<String, Object> sourceMap = asMap(bson);
|
||||
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, sourceMap.keySet().size());
|
||||
|
||||
if (!DBRef.class.equals(rawValueType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceMap.values())) {
|
||||
bulkReadAndConvertDBRefMapIntoTarget(valueType.orElse(null), rawValueType, sourceMap, map);
|
||||
bulkReadAndConvertDBRefMapIntoTarget(valueType, rawValueType, sourceMap, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -961,12 +1018,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Object key = potentiallyUnescapeMapKey(entry.getKey());
|
||||
|
||||
if (rawKeyType != null) {
|
||||
if (rawKeyType != null && !rawKeyType.isAssignableFrom(key.getClass())) {
|
||||
key = conversionService.convert(key, rawKeyType);
|
||||
}
|
||||
|
||||
Object value = entry.getValue();
|
||||
TypeInformation<?> defaultedValueType = valueType.orElse(ClassTypeInformation.OBJECT);
|
||||
TypeInformation<?> defaultedValueType = valueType != null ? valueType : ClassTypeInformation.OBJECT;
|
||||
|
||||
if (value instanceof Document) {
|
||||
map.put(key, read(defaultedValueType, (Document) value, path));
|
||||
@@ -976,7 +1033,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
map.put(key, DBRef.class.equals(rawValueType) ? value
|
||||
: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType));
|
||||
} else if (value instanceof List) {
|
||||
map.put(key, readCollectionOrArray(valueType.orElse(ClassTypeInformation.LIST), (List) value, path));
|
||||
map.put(key,
|
||||
readCollectionOrArray(valueType != null ? valueType : ClassTypeInformation.LIST, (List) value, path));
|
||||
} else {
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, rawValueType));
|
||||
}
|
||||
@@ -1098,7 +1156,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
if (obj instanceof Map) {
|
||||
|
||||
Map<Object, Object> converted = new LinkedHashMap<>(((Map) obj).size(), 1);
|
||||
Document result = new Document();
|
||||
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||
@@ -1199,7 +1256,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
|
||||
class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
|
||||
|
||||
private final DocumentAccessor source;
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
@@ -1224,17 +1281,39 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator} and
|
||||
* {@link ObjectPath}.
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param evaluator must not be {@literal null}.
|
||||
* @param path can be {@literal null}.
|
||||
*/
|
||||
public MongoDbPropertyValueProvider(DocumentAccessor accessor, SpELExpressionEvaluator evaluator, ObjectPath path) {
|
||||
|
||||
Assert.notNull(accessor, "DocumentAccessor must no be null!");
|
||||
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null!");
|
||||
Assert.notNull(path, "ObjectPath must not be null!");
|
||||
|
||||
this.source = accessor;
|
||||
this.evaluator = evaluator;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
public <T> Optional<T> getPropertyValue(MongoPersistentProperty property) {
|
||||
return Optional
|
||||
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||
|
||||
.ofNullable(property.getSpelExpression()//
|
||||
.map(evaluator::evaluate)//
|
||||
.orElseGet(() -> source.get(property)))//
|
||||
.map(it -> readValue(it, property.getTypeInformation(), path));
|
||||
String expression = property.getSpelExpression();
|
||||
Object value = expression != null ? evaluator.evaluate(expression) : source.get(property);
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return readValue(value, property.getTypeInformation(), path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,7 +1354,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T readValue(Object value, TypeInformation<?> type, ObjectPath path) {
|
||||
<T> T readValue(Object value, TypeInformation<?> type, ObjectPath path) {
|
||||
|
||||
Class<?> rawType = type.getType();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,17 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.Document;
|
||||
@@ -41,7 +32,6 @@ import org.springframework.data.mongodb.core.query.MongoRegexCreator;
|
||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||
import org.springframework.data.repository.core.support.ExampleMatcherAccessor;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -99,8 +89,12 @@ public class MongoExampleMapper {
|
||||
|
||||
Document reference = (Document) converter.convertToMongoType(example.getProbe());
|
||||
|
||||
if(entity.getIdProperty().isPresent() && !entity.getIdentifierAccessor(example.getProbe()).getIdentifier().isPresent()) {
|
||||
reference.remove(entity.getIdProperty().get().getFieldName());
|
||||
if (entity.getIdProperty() != null) {
|
||||
|
||||
Object identifier = entity.getIdentifierAccessor(example.getProbe()).getIdentifier();
|
||||
if (identifier == null) {
|
||||
reference.remove(entity.getIdProperty().getFieldName());
|
||||
}
|
||||
}
|
||||
|
||||
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
|
||||
@@ -153,7 +147,7 @@ public class MongoExampleMapper {
|
||||
while (parts.hasNext()) {
|
||||
|
||||
String part = parts.next();
|
||||
MongoPersistentProperty prop = entity.getPersistentProperty(part).orElse(null);
|
||||
MongoPersistentProperty prop = entity.getPersistentProperty(part);
|
||||
|
||||
if (prop == null) {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,7 @@
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -31,34 +29,36 @@ import org.springframework.util.StringUtils;
|
||||
* <p>
|
||||
* An immutable ordered set of target objects for {@link Document} to {@link Object} conversions. Object paths can be
|
||||
* constructed by the {@link #toObjectPath(Object)} method and extended via {@link #push(Object)}.
|
||||
*
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.6
|
||||
*/
|
||||
class ObjectPath {
|
||||
|
||||
public static final ObjectPath ROOT = new ObjectPath();
|
||||
|
||||
private final List<ObjectPathItem> items;
|
||||
private final ObjectPathItem[] items;
|
||||
|
||||
private ObjectPath() {
|
||||
this.items = Collections.emptyList();
|
||||
this.items = new ObjectPathItem[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPath} from the given parent {@link ObjectPath} by adding the provided
|
||||
* {@link ObjectPathItem} to it.
|
||||
*
|
||||
*
|
||||
* @param parent can be {@literal null}.
|
||||
* @param item
|
||||
*/
|
||||
private ObjectPath(ObjectPath parent, ObjectPath.ObjectPathItem item) {
|
||||
|
||||
List<ObjectPath.ObjectPathItem> items = new ArrayList<ObjectPath.ObjectPathItem>(parent.items);
|
||||
items.add(item);
|
||||
ObjectPathItem[] items = new ObjectPathItem[parent.items.length + 1];
|
||||
System.arraycopy(parent.items, 0, items, 0, parent.items.length);
|
||||
items[parent.items.length] = item;
|
||||
|
||||
this.items = Collections.unmodifiableList(items);
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ class ObjectPath {
|
||||
/**
|
||||
* Returns the object with the given id and stored in the given collection if it's contained in the {@link ObjectPath}
|
||||
* .
|
||||
*
|
||||
*
|
||||
* @param id must not be {@literal null}.
|
||||
* @param collection must not be {@literal null} or empty.
|
||||
* @return
|
||||
@@ -113,25 +113,25 @@ class ObjectPath {
|
||||
|
||||
/**
|
||||
* Returns the current object of the {@link ObjectPath} or {@literal null} if the path is empty.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Optional<Object> getCurrentObject() {
|
||||
return items.isEmpty() ? Optional.empty() : Optional.of(items.get(items.size() - 1).getObject());
|
||||
public Object getCurrentObject() {
|
||||
return items.length == 0 ? null : items[items.length - 1].getObject();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
if (items.isEmpty()) {
|
||||
if (items.length == 0) {
|
||||
return "[empty]";
|
||||
}
|
||||
|
||||
List<String> strings = new ArrayList<String>(items.size());
|
||||
List<String> strings = new ArrayList<String>(items.length);
|
||||
|
||||
for (ObjectPathItem item : items) {
|
||||
strings.add(item.object.toString());
|
||||
@@ -142,7 +142,7 @@ class ObjectPath {
|
||||
|
||||
/**
|
||||
* An item in an {@link ObjectPath}.
|
||||
*
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -154,7 +154,7 @@ class ObjectPath {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ObjectPathItem}.
|
||||
*
|
||||
*
|
||||
* @param object
|
||||
* @param idValue
|
||||
* @param collection
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.data.mapping.PropertyReferenceException;
|
||||
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter.NestedDocument;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
@@ -122,7 +122,7 @@ public class QueryMapper {
|
||||
if (Query.isRestrictedTypeKey(key)) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Class<?>> restrictedTypes = (Set<Class<?>>) BsonUtils.get(query, key);
|
||||
Set<Class<?>> restrictedTypes = BsonUtils.get(query, key);
|
||||
this.converter.getTypeMapper().writeTypeRestrictions(result, restrictedTypes);
|
||||
|
||||
continue;
|
||||
@@ -318,11 +318,11 @@ public class QueryMapper {
|
||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id).get());
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
resultDbo.put(inKey, ids);
|
||||
} else if (valueDbo.containsField("$ne")) {
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")).get());
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
return getMappedObject(resultDbo, Optional.empty());
|
||||
}
|
||||
@@ -337,18 +337,18 @@ public class QueryMapper {
|
||||
String inKey = valueDbo.containsKey("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id).orElse(null));
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
resultDbo.put(inKey, ids);
|
||||
} else if (valueDbo.containsKey("$ne")) {
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")).orElse(null));
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
return getMappedObject(resultDbo, Optional.empty());
|
||||
}
|
||||
return resultDbo;
|
||||
|
||||
} else {
|
||||
return convertId(value).orElse(null);
|
||||
return convertId(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ public class QueryMapper {
|
||||
|
||||
MongoPersistentEntity<?> entity = documentField.getPropertyEntity();
|
||||
return entity.hasIdProperty() && (type.equals(DBRef.class)
|
||||
|| entity.getIdProperty().map(it -> it.getActualType().isAssignableFrom(type)).orElse(false));
|
||||
|| entity.getRequiredIdProperty().getActualType().isAssignableFrom(type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -461,7 +461,7 @@ public class QueryMapper {
|
||||
if (source instanceof DBRef) {
|
||||
|
||||
DBRef ref = (DBRef) source;
|
||||
return new DBRef(ref.getCollectionName(), convertId(ref.getId()).get());
|
||||
return new DBRef(ref.getCollectionName(), convertId(ref.getId()));
|
||||
}
|
||||
|
||||
if (source instanceof Iterable) {
|
||||
@@ -537,31 +537,28 @@ public class QueryMapper {
|
||||
return converter.toDBRef(source, property);
|
||||
}
|
||||
|
||||
private Optional<Object> convertId(Object id) {
|
||||
return convertId(Optional.ofNullable(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public Optional<Object> convertId(Optional<Object> id) {
|
||||
public Object convertId(Object id) {
|
||||
|
||||
return id.map(it -> {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (it instanceof String) {
|
||||
return ObjectId.isValid(it.toString()) ? conversionService.convert(it, ObjectId.class) : it;
|
||||
}
|
||||
if (id instanceof String) {
|
||||
return ObjectId.isValid(id.toString()) ? conversionService.convert(id, ObjectId.class) : id;
|
||||
}
|
||||
|
||||
try {
|
||||
return conversionService.canConvert(it.getClass(), ObjectId.class)
|
||||
? conversionService.convert(it, ObjectId.class) : delegateConvertToMongoType(it, null);
|
||||
} catch (ConversionException o_O) {
|
||||
return delegateConvertToMongoType(it, null);
|
||||
}
|
||||
});
|
||||
try {
|
||||
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService.convert(id, ObjectId.class)
|
||||
: delegateConvertToMongoType(id, null);
|
||||
} catch (ConversionException o_O) {
|
||||
return delegateConvertToMongoType(id, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -836,9 +833,13 @@ public class QueryMapper {
|
||||
@Override
|
||||
public boolean isIdField() {
|
||||
|
||||
return entity.getIdProperty()//
|
||||
.map(it -> it.getName().equals(name) || it.getFieldName().equals(name))//
|
||||
.orElseGet(() -> DEFAULT_ID_NAMES.contains(name));
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
return idProperty.getName().equals(name) || idProperty.getFieldName().equals(name);
|
||||
}
|
||||
|
||||
return DEFAULT_ID_NAMES.contains(name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -857,7 +858,7 @@ public class QueryMapper {
|
||||
@Override
|
||||
public MongoPersistentEntity<?> getPropertyEntity() {
|
||||
MongoPersistentProperty property = getProperty();
|
||||
return property == null ? null : mappingContext.getPersistentEntity(property).orElse(null);
|
||||
return property == null ? null : mappingContext.getPersistentEntity(property);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -883,15 +884,15 @@ public class QueryMapper {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private final Association<MongoPersistentProperty> findAssociation() {
|
||||
private Association<MongoPersistentProperty> findAssociation() {
|
||||
|
||||
if (this.path != null) {
|
||||
for (MongoPersistentProperty p : this.path) {
|
||||
|
||||
Optional<Association<MongoPersistentProperty>> association = p.getAssociation();
|
||||
Association<MongoPersistentProperty> association = p.getAssociation();
|
||||
|
||||
if (association.isPresent()) {
|
||||
return association.get();
|
||||
if (association != null) {
|
||||
return association;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
@@ -24,7 +22,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
/**
|
||||
* Internal API to trigger the resolution of properties.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@@ -33,13 +31,13 @@ interface ValueResolver {
|
||||
/**
|
||||
* Resolves the value for the given {@link MongoPersistentProperty} within the given {@link Document} using the given
|
||||
* {@link SpELExpressionEvaluator} and {@link ObjectPath}.
|
||||
*
|
||||
*
|
||||
* @param prop
|
||||
* @param bson
|
||||
* @param evaluator
|
||||
* @param parent
|
||||
* @return
|
||||
*/
|
||||
Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
ObjectPath path);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
|
||||
|
||||
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (entity.findAnnotation(Document.class).isPresent()) {
|
||||
if (entity.isAnnotationPresent(Document.class)) {
|
||||
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
|
||||
createIndex(indexToCreate);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -33,7 +32,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexedFieldSpec;
|
||||
@@ -94,7 +93,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
public List<IndexDefinitionHolder> resolveIndexForEntity(final MongoPersistentEntity<?> root) {
|
||||
|
||||
Assert.notNull(root, "Index cannot be resolved for given 'null' entity.");
|
||||
Document document = root.findAnnotation(Document.class).orElseThrow(() -> new IllegalArgumentException("Given entity is not collection root."));
|
||||
Document document = root.findAnnotation(Document.class);
|
||||
Assert.notNull(document, "Given entity is not collection root.");
|
||||
|
||||
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
|
||||
@@ -255,20 +254,20 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
indexDefinitionBuilder.withLanguageOverride(persistentProperty.getFieldName());
|
||||
}
|
||||
|
||||
Optional<TextIndexed> indexed = persistentProperty.findAnnotation(TextIndexed.class);
|
||||
TextIndexed indexed = persistentProperty.findAnnotation(TextIndexed.class);
|
||||
|
||||
if (includeOptions.isForce() || indexed.isPresent()|| persistentProperty.isEntity()) {
|
||||
if (includeOptions.isForce() || indexed != null || persistentProperty.isEntity()) {
|
||||
|
||||
String propertyDotPath = (StringUtils.hasText(dotPath) ? dotPath + "." : "")
|
||||
+ persistentProperty.getFieldName();
|
||||
|
||||
Float weight = indexed.isPresent() ? indexed.get().weight()
|
||||
Float weight = indexed != null ? indexed.weight()
|
||||
: (includeOptions.getParentFieldSpec() != null ? includeOptions.getParentFieldSpec().getWeight() : 1.0F);
|
||||
|
||||
if (persistentProperty.isEntity()) {
|
||||
|
||||
TextIndexIncludeOptions optionsForNestedType = includeOptions;
|
||||
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed.isPresent()) {
|
||||
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
|
||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
|
||||
new TextIndexedFieldSpec(propertyDotPath, weight));
|
||||
}
|
||||
@@ -282,7 +281,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||
entity.getName()), e);
|
||||
}
|
||||
} else if (includeOptions.isForce() || indexed.isPresent()) {
|
||||
} else if (includeOptions.isForce() || indexed != null) {
|
||||
indexDefinitionBuilder.onField(propertyDotPath, weight);
|
||||
}
|
||||
}
|
||||
@@ -304,18 +303,18 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
MongoPersistentEntity<?> entity) {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
|
||||
Optional<CompoundIndexes> indexes = entity.findAnnotation(CompoundIndexes.class);
|
||||
CompoundIndexes indexes = entity.findAnnotation(CompoundIndexes.class);
|
||||
|
||||
if (indexes.isPresent()) {
|
||||
for (CompoundIndex index : indexes.get().value()) {
|
||||
if (indexes != null) {
|
||||
for (CompoundIndex index : indexes.value()) {
|
||||
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
|
||||
}
|
||||
}
|
||||
|
||||
Optional<CompoundIndex> index = entity.findAnnotation(CompoundIndex.class);
|
||||
CompoundIndex index = entity.findAnnotation(CompoundIndex.class);
|
||||
|
||||
if (index.isPresent()) {
|
||||
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index.get(), entity));
|
||||
if (index != null) {
|
||||
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
|
||||
}
|
||||
|
||||
return indexDefinitions;
|
||||
@@ -382,33 +381,33 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
protected IndexDefinitionHolder createIndexDefinition(String dotPath, String collection,
|
||||
MongoPersistentProperty persitentProperty) {
|
||||
|
||||
Optional<Indexed> index = persitentProperty.findAnnotation(Indexed.class);
|
||||
Indexed index = persitentProperty.findAnnotation(Indexed.class);
|
||||
|
||||
if(!index.isPresent()){
|
||||
if (index == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Index indexDefinition = new Index().on(dotPath,
|
||||
IndexDirection.ASCENDING.equals(index.get().direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
|
||||
IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
|
||||
|
||||
if (!index.get().useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.get().name(), dotPath, persitentProperty));
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persitentProperty));
|
||||
}
|
||||
|
||||
if (index.get().unique()) {
|
||||
if (index.unique()) {
|
||||
indexDefinition.unique();
|
||||
}
|
||||
|
||||
if (index.get().sparse()) {
|
||||
if (index.sparse()) {
|
||||
indexDefinition.sparse();
|
||||
}
|
||||
|
||||
if (index.get().background()) {
|
||||
if (index.background()) {
|
||||
indexDefinition.background();
|
||||
}
|
||||
|
||||
if (index.get().expireAfterSeconds() >= 0) {
|
||||
indexDefinition.expire(index.get().expireAfterSeconds(), TimeUnit.SECONDS);
|
||||
if (index.expireAfterSeconds() >= 0) {
|
||||
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
@@ -426,21 +425,21 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
protected IndexDefinitionHolder createGeoSpatialIndexDefinition(String dotPath, String collection,
|
||||
MongoPersistentProperty persistentProperty) {
|
||||
|
||||
Optional<GeoSpatialIndexed> index = persistentProperty.findAnnotation(GeoSpatialIndexed.class);
|
||||
GeoSpatialIndexed index = persistentProperty.findAnnotation(GeoSpatialIndexed.class);
|
||||
|
||||
if(!index.isPresent()) {
|
||||
if (index == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GeospatialIndex indexDefinition = new GeospatialIndex(dotPath);
|
||||
indexDefinition.withBits(index.get().bits());
|
||||
indexDefinition.withMin(index.get().min()).withMax(index.get().max());
|
||||
indexDefinition.withBits(index.bits());
|
||||
indexDefinition.withMin(index.min()).withMax(index.max());
|
||||
|
||||
if (!index.get().useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.get().name(), dotPath, persistentProperty));
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persistentProperty));
|
||||
}
|
||||
|
||||
indexDefinition.typed(index.get().type()).withBucketSize(index.get().bucketSize()).withAdditionalField(index.get().additionalField());
|
||||
indexDefinition.typed(index.type()).withBucketSize(index.bucketSize()).withAdditionalField(index.additionalField());
|
||||
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -32,7 +31,7 @@ import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.MongoCollectionUtils;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.Expression;
|
||||
@@ -47,7 +46,7 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* MongoDB specific {@link MongoPersistentEntity} implementation that adds Mongo specific meta-data such as the
|
||||
* collection name and the like.
|
||||
*
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
@@ -69,23 +68,30 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
/**
|
||||
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
|
||||
* collection name to the entities simple type name.
|
||||
*
|
||||
*
|
||||
* @param typeInformation must not be {@literal null}.
|
||||
*/
|
||||
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
super(typeInformation, Optional.of(MongoPersistentPropertyComparator.INSTANCE));
|
||||
super(typeInformation, MongoPersistentPropertyComparator.INSTANCE);
|
||||
|
||||
Class<?> rawType = typeInformation.getType();
|
||||
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
|
||||
|
||||
Optional<Document> document = this.findAnnotation(Document.class);
|
||||
|
||||
this.expression = document.map(it -> detectExpression(it)).orElse(null);
|
||||
this.context = new StandardEvaluationContext();
|
||||
this.collection = document.filter(it -> StringUtils.hasText(it.collection())).map(it -> it.collection())
|
||||
.orElse(fallback);
|
||||
this.language = document.filter(it -> StringUtils.hasText(it.language())).map(it -> it.language()).orElse("");
|
||||
|
||||
if (this.isAnnotationPresent(Document.class)) {
|
||||
Document document = this.findAnnotation(Document.class);
|
||||
|
||||
this.collection = StringUtils.hasText(document.collection()) ? document.collection() : fallback;
|
||||
this.language = StringUtils.hasText(document.language()) ? document.language() : "";
|
||||
this.expression = document != null ? detectExpression(document) : null;
|
||||
} else {
|
||||
|
||||
this.collection = fallback;
|
||||
this.language = "";
|
||||
this.expression = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -122,7 +128,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
*/
|
||||
@Override
|
||||
public MongoPersistentProperty getTextScoreProperty() {
|
||||
return getPersistentProperty(TextScore.class).orElse(null);
|
||||
return getPersistentProperty(TextScore.class);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -159,7 +165,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
|
||||
/**
|
||||
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static enum MongoPersistentPropertyComparator implements Comparator<MongoPersistentProperty> {
|
||||
@@ -189,7 +195,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
* that is annotated with @see {@link Id}. The property id is updated according to the following rules: 1) An id
|
||||
* property which is defined explicitly takes precedence over an implicitly defined id property. 2) In case of any
|
||||
* ambiguity a @see {@link MappingException} is thrown.
|
||||
*
|
||||
*
|
||||
* @param property - the new id property candidate
|
||||
* @return
|
||||
*/
|
||||
@@ -202,45 +208,47 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
return null;
|
||||
}
|
||||
|
||||
Optional<MongoPersistentProperty> currentIdProperty = getIdProperty();
|
||||
MongoPersistentProperty currentIdProperty = getIdProperty();
|
||||
|
||||
return currentIdProperty.map(it -> {
|
||||
boolean currentIdPropertyIsSet = currentIdProperty != null;
|
||||
@SuppressWarnings("null")
|
||||
boolean currentIdPropertyIsExplicit = currentIdPropertyIsSet ? currentIdProperty.isExplicitIdProperty() : false;
|
||||
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
|
||||
|
||||
boolean currentIdPropertyIsExplicit = it.isExplicitIdProperty();
|
||||
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
|
||||
Optional<Field> currentIdPropertyField = it.getField();
|
||||
if (!currentIdPropertyIsSet) {
|
||||
return property;
|
||||
|
||||
if (newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
"Attempt to add explicit id property %s but already have an property %s registered "
|
||||
+ "as explicit id. Check your mapping configuration!",
|
||||
property.getField(), currentIdPropertyField));
|
||||
}
|
||||
|
||||
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
|
||||
// explicit id property takes precedence over implicit id property
|
||||
return property;
|
||||
@SuppressWarnings("null")
|
||||
Field currentIdPropertyField = currentIdProperty.getField();
|
||||
|
||||
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||
// no id property override - current property is explicitly defined
|
||||
if (newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||
throw new MappingException(
|
||||
String.format("Attempt to add explicit id property %s but already have an property %s registered "
|
||||
+ "as explicit id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
|
||||
|
||||
} else {
|
||||
throw new MappingException(
|
||||
String.format("Attempt to add id property %s but already have an property %s registered "
|
||||
+ "as id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
|
||||
}
|
||||
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
|
||||
// explicit id property takes precedence over implicit id property
|
||||
return property;
|
||||
|
||||
return null;
|
||||
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||
// no id property override - current property is explicitly defined
|
||||
|
||||
}).orElse(property);
|
||||
} else {
|
||||
throw new MappingException(
|
||||
String.format("Attempt to add id property %s but already have an property %s registered "
|
||||
+ "as id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SpEL {@link Expression} frór the collection String expressed in the given {@link Document} annotation if
|
||||
* present or {@literal null} otherwise. Will also return {@literal null} it the collection {@link String} evaluates
|
||||
* to a {@link LiteralExpression} (indicating that no subsequent evaluation is necessary).
|
||||
*
|
||||
*
|
||||
* @param document can be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
@@ -264,7 +272,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
/**
|
||||
* Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct
|
||||
* field name.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class AssertFieldNameUniquenessHandler
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
@@ -27,19 +26,20 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* MongoDB specific {@link org.springframework.data.mapping.MongoPersistentProperty} implementation.
|
||||
*
|
||||
* MongoDB specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Patryk Wasik
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty>
|
||||
implements MongoPersistentProperty {
|
||||
@@ -65,7 +65,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicMongoPersistentProperty}.
|
||||
*
|
||||
*
|
||||
* @param field
|
||||
* @param propertyDescriptor
|
||||
* @param owner
|
||||
@@ -86,7 +86,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
/**
|
||||
* Also considers fields as id that are of supported id type and name.
|
||||
*
|
||||
*
|
||||
* @see #SUPPORTED_ID_PROPERTY_NAMES
|
||||
* @see #SUPPORTED_ID_TYPES
|
||||
*/
|
||||
@@ -113,14 +113,14 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
/**
|
||||
* Returns the key to be used to store the value of the property inside a Mongo {@link org.bson.Document}.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getFieldName() {
|
||||
|
||||
if (isIdProperty()) {
|
||||
|
||||
if (!getOwner().getIdProperty().isPresent()) {
|
||||
if (getOwner().getIdProperty() == null) {
|
||||
return ID_FIELD_NAME;
|
||||
}
|
||||
|
||||
@@ -154,13 +154,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
private String getAnnotatedFieldName() {
|
||||
|
||||
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
||||
|
||||
return annotation//
|
||||
.filter(it -> StringUtils.hasText(it.value()))//
|
||||
.map(it -> it.value())//
|
||||
.orElse(null);
|
||||
return annotation != null ? annotation.value() : null;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -169,10 +166,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
*/
|
||||
public int getFieldOrder() {
|
||||
|
||||
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
||||
|
||||
return annotation.map(it -> it.order()).orElse(Integer.MAX_VALUE);
|
||||
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -197,7 +194,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef()
|
||||
*/
|
||||
public DBRef getDBRef() {
|
||||
return findAnnotation(DBRef.class).orElse(null);
|
||||
return findAnnotation(DBRef.class);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.springframework.data.util.Optionals;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value(staticConstructor = "of")
|
||||
public class EntityHandler<T extends MongoPersistentEntity<?>> {
|
||||
|
||||
Optional<T> entity;
|
||||
|
||||
public void doWithVersionProperty(BiConsumer<T, MongoPersistentProperty> consumer) {
|
||||
|
||||
Optionals.ifAllPresent(entity, entity.flatMap(it -> it.getVersionProperty()), consumer);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
@@ -36,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
* {@link Converter} to instantiate DTOs from fully equipped domain objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
|
||||
@@ -45,7 +44,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Converter} to instantiate DTOs.
|
||||
*
|
||||
*
|
||||
* @param dtoType must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param instantiators must not be {@literal null}.
|
||||
@@ -63,7 +62,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
this.instantiator = instantiator.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@@ -78,14 +77,14 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
final PersistentPropertyAccessor sourceAccessor = sourceEntity.getPropertyAccessor(source);
|
||||
final PersistentEntity<?, ?> targetEntity = context.getRequiredPersistentEntity(targetType);
|
||||
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor = targetEntity
|
||||
.getPersistenceConstructor().get();
|
||||
.getPersistenceConstructor();
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object dto = instantiator.createInstance(targetEntity, new ParameterValueProvider() {
|
||||
|
||||
@Override
|
||||
public Optional<Object> getParameterValue(Parameter parameter) {
|
||||
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName().get().toString()).get());
|
||||
public Object getParameterValue(Parameter parameter) {
|
||||
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName().toString()));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,7 +100,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
}
|
||||
|
||||
dtoAccessor.setProperty(property,
|
||||
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName()).get()));
|
||||
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName())));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Custom extension of {@link Parameters} discovering additional
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@@ -47,7 +47,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParameters} instance from the given {@link Method} and {@link MongoQueryMethod}.
|
||||
*
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
*/
|
||||
@@ -115,8 +115,8 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
if (this.nearIndex == null && mongoParameter.isManuallyAnnotatedNearParameter()) {
|
||||
this.nearIndex = mongoParameter.getIndex();
|
||||
} else if (mongoParameter.isManuallyAnnotatedNearParameter()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
|
||||
throw new IllegalStateException(String.format("Found multiple @Near annotations ond method %s! Only one allowed!",
|
||||
parameter.getMethod().toString()));
|
||||
}
|
||||
|
||||
return mongoParameter;
|
||||
@@ -128,7 +128,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Returns the index of the {@link Distance} parameter to be used for max distance in geo queries.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @since 1.7
|
||||
*/
|
||||
@@ -138,7 +138,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Returns the index of the parameter to be used to start a geo-near query from.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNearIndex() {
|
||||
@@ -147,7 +147,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Returns ths inde of the parameter to be used as a textquery param
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
@@ -171,7 +171,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
return rangeIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.Parameters#createFrom(java.util.List)
|
||||
*/
|
||||
@@ -190,7 +190,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
if (componentType == null) {
|
||||
return i;
|
||||
} else if (componentType.equals(candidate.getComponentType().get().getType())) {
|
||||
} else if (componentType.equals(candidate.getRequiredComponentType().getType())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MongoParameter extends Parameter {
|
||||
@@ -210,7 +210,7 @@ public class MongoParameters extends Parameters<MongoParameters, MongoParameter>
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParameter}.
|
||||
*
|
||||
*
|
||||
* @param parameter must not be {@literal null}.
|
||||
*/
|
||||
MongoParameter(MethodParameter parameter) {
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Custom query creator to create Mongo criterias.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
@@ -68,7 +68,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
/**
|
||||
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and
|
||||
* {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param tree
|
||||
* @param accessor
|
||||
* @param context
|
||||
@@ -81,7 +81,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
/**
|
||||
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and
|
||||
* {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param tree
|
||||
* @param accessor
|
||||
* @param context
|
||||
@@ -163,7 +163,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
/**
|
||||
* Populates the given {@link CriteriaDefinition} depending on the {@link Part} given.
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
* @param property
|
||||
* @param criteria
|
||||
@@ -272,7 +272,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
/**
|
||||
* Creates and extends the given criteria with a like-regex if necessary.
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
* @param property
|
||||
* @param criteria
|
||||
@@ -314,7 +314,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
* If the target property of the comparison is of type String, then the operator checks for match using regular
|
||||
* expression. If the target property of the comparison is a {@link Collection} then the operator evaluates to true if
|
||||
* it finds an exact match within any member of the {@link Collection}.
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
* @param property
|
||||
* @param criteria
|
||||
@@ -333,7 +333,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
/**
|
||||
* Creates an appropriate like-regex and appends it to the given criteria.
|
||||
*
|
||||
*
|
||||
* @param criteria
|
||||
* @param part
|
||||
* @param value
|
||||
@@ -368,7 +368,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
/**
|
||||
* Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
* @param iterator
|
||||
* @param type
|
||||
@@ -407,7 +407,11 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
private boolean isSpherical(MongoPersistentProperty property) {
|
||||
|
||||
Optional<GeoSpatialIndexed> index = property.findAnnotation(GeoSpatialIndexed.class);
|
||||
return index.isPresent() && index.get().type().equals(GeoSpatialIndexType.GEO_2DSPHERE);
|
||||
if (property.isAnnotationPresent(GeoSpatialIndexed.class)) {
|
||||
GeoSpatialIndexed index = property.findAnnotation(GeoSpatialIndexed.class);
|
||||
return index.type().equals(GeoSpatialIndexType.GEO_2DSPHERE);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -62,7 +62,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for collection returning queries.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@@ -83,7 +83,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for {@link Slice} query methods.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
@@ -116,7 +116,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for pagination queries.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -154,7 +154,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} to return a single entity.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@@ -217,7 +217,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} to execute geo-near queries.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@@ -267,8 +267,8 @@ interface MongoQueryExecution {
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<TypeInformation<?>> componentType = returnType.getComponentType();
|
||||
return componentType.isPresent() && GeoResult.class.equals(componentType.get().getType());
|
||||
TypeInformation<?> componentType = returnType.getComponentType();
|
||||
return componentType != null && GeoResult.class.equals(componentType.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ interface MongoQueryExecution {
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} removing documents matching the query.
|
||||
*
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@@ -388,7 +388,7 @@ interface MongoQueryExecution {
|
||||
private final @NonNull MongoQueryExecution delegate;
|
||||
private final @NonNull Converter<Object, Object> converter;
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@@ -411,7 +411,7 @@ interface MongoQueryExecution {
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final @NonNull EntityInstantiators instantiators;
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
|
||||
@@ -147,14 +147,14 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
|
||||
} else {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
|
||||
MongoPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
|
||||
MongoPersistentEntity<?> managedEntity = mappingContext.getRequiredPersistentEntity(domainClass);
|
||||
returnedEntity = !returnedEntity.isPresent() || returnedEntity.get().getType().isInterface() ? Optional.of(managedEntity)
|
||||
returnedEntity = returnedEntity == null || returnedEntity.getType().isInterface() ? managedEntity
|
||||
: returnedEntity;
|
||||
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity.get()
|
||||
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
|
||||
: managedEntity;
|
||||
|
||||
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.get().getType(),
|
||||
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
|
||||
collectionEntity);
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
|
||||
if (Iterable.class.isAssignableFrom(returnType)) {
|
||||
TypeInformation<?> from = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
return GeoResult.class.equals(from.getComponentType().get().getType());
|
||||
return GeoResult.class.equals(from.getRequiredComponentType().getType());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,6 @@ import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -154,8 +152,8 @@ interface ReactiveMongoQueryExecution {
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<TypeInformation<?>> componentType = returnType.getComponentType();
|
||||
return componentType.isPresent() && GeoResult.class.equals(componentType.get().getType());
|
||||
TypeInformation<?> componentType = returnType.getComponentType();
|
||||
return componentType != null && GeoResult.class.equals(componentType.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
|
||||
boolean multiWrapper = ReactiveWrappers.isMultiValueType(returnType.getType());
|
||||
boolean singleWrapperWithWrappedPageableResult = ReactiveWrappers.isSingleValueType(returnType.getType())
|
||||
&& (PAGE_TYPE.isAssignableFrom(returnType.getComponentType().get())
|
||||
|| SLICE_TYPE.isAssignableFrom(returnType.getComponentType().get()));
|
||||
&& (PAGE_TYPE.isAssignableFrom(returnType.getRequiredComponentType())
|
||||
|| SLICE_TYPE.isAssignableFrom(returnType.getRequiredComponentType()));
|
||||
|
||||
if (singleWrapperWithWrappedPageableResult) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
@@ -94,7 +94,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoQueryMethod#createParameters(java.lang.reflect.Method)
|
||||
*/
|
||||
@@ -103,7 +103,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
return new MongoParameters(method, isGeoNearQuery(method));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#isCollectionQuery()
|
||||
*/
|
||||
@@ -112,7 +112,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
return !(isPageQuery() || isSliceQuery()) && ReactiveWrappers.isMultiValueType(method.getReturnType());
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoQueryMethod#isGeoNearQuery()
|
||||
*/
|
||||
@@ -125,13 +125,13 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
|
||||
if (ReactiveWrappers.supports(method.getReturnType())) {
|
||||
TypeInformation<?> from = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
return GeoResult.class.equals(from.getComponentType().get().getType());
|
||||
return GeoResult.class.equals(from.getRequiredComponentType().getType());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#isModifyingQuery()
|
||||
*/
|
||||
@@ -140,7 +140,7 @@ public class ReactiveMongoQueryMethod extends MongoQueryMethod {
|
||||
return super.isModifyingQuery();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#isQueryForEntity()
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright 2011-2017 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,9 +24,10 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat
|
||||
* {@link MongoEntityInformation} implementation using a {@link MongoPersistentEntity} instance to lookup the necessary
|
||||
* information. Can be configured with a custom collection to be returned which will trump the one returned by the
|
||||
* {@link MongoPersistentEntity} if given.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
|
||||
implements MongoEntityInformation<T, ID> {
|
||||
@@ -37,7 +38,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
|
||||
@@ -47,18 +48,18 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and fallback
|
||||
* identifier type.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param fallbackIdType can be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, Class<ID> fallbackIdType) {
|
||||
this(entity, (String) null, fallbackIdType);
|
||||
this(entity, null, fallbackIdType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and custom
|
||||
* collection name.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
*/
|
||||
@@ -69,7 +70,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}, collection name
|
||||
* and identifier type.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
* @param idType can be {@literal null}.
|
||||
@@ -96,7 +97,7 @@ public class MappingMongoEntityInformation<T, ID> extends PersistentEntityInform
|
||||
* @see org.springframework.data.mongodb.repository.MongoEntityInformation#getIdAttribute()
|
||||
*/
|
||||
public String getIdAttribute() {
|
||||
return entityMetadata.getIdProperty().get().getName();
|
||||
return entityMetadata.getRequiredIdProperty().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.data.mongodb.repository.support;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
|
||||
@@ -76,10 +74,10 @@ class PersistableMongoEntityInformation<T, ID> implements MongoEntityInformation
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Optional<ID> getId(T t) {
|
||||
public ID getId(T t) {
|
||||
|
||||
if (t instanceof Persistable) {
|
||||
return Optional.ofNullable(((Persistable<ID>) t).getId());
|
||||
return ((Persistable<ID>) t).getId();
|
||||
}
|
||||
|
||||
return delegate.getId(t);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,10 +33,10 @@ import org.springframework.util.ClassUtils;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.querydsl.core.types.Constant;
|
||||
import com.querydsl.core.types.Expression;
|
||||
import com.querydsl.core.types.Operation;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.PathMetadata;
|
||||
import com.querydsl.core.types.PathType;
|
||||
@@ -44,7 +44,7 @@ import com.querydsl.mongodb.MongodbSerializer;
|
||||
|
||||
/**
|
||||
* Custom {@link MongodbSerializer} to take mapping information into account when building keys for constraints.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
@@ -69,7 +69,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
/**
|
||||
* Creates a new {@link SpringDataMongodbSerializer} for the given {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
public SpringDataMongodbSerializer(MongoConverter converter) {
|
||||
@@ -108,9 +108,9 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
Path<?> parent = metadata.getParent();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(parent.getType());
|
||||
Optional<MongoPersistentProperty> property = entity.getPersistentProperty(metadata.getName());
|
||||
MongoPersistentProperty property = entity.getPersistentProperty(metadata.getName());
|
||||
|
||||
return !property.isPresent() ? super.getKeyForPath(expr, metadata) : property.get().getFieldName();
|
||||
return property == null ? super.getKeyForPath(expr, metadata) : property.getFieldName();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -120,7 +120,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
@Override
|
||||
protected DBObject asDBObject(String key, Object value) {
|
||||
|
||||
value = value instanceof Optional ? ((Optional)value).orElse(null) : value;
|
||||
value = value instanceof Optional ? ((Optional) value).orElse(null) : value;
|
||||
|
||||
if (ID_KEY.equals(key)) {
|
||||
DBObject superIdValue = super.asDBObject(key, value);
|
||||
@@ -203,8 +203,8 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
return null;
|
||||
}
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(parent.getType());
|
||||
return entity.isPresent() ? entity.get().getRequiredPersistentProperty(path.getMetadata().getName()) : null;
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(parent.getType());
|
||||
return entity != null ? entity.getRequiredPersistentProperty(path.getMetadata().getName()) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,7 +46,7 @@ import com.mongodb.client.MongoCollection;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DefaultBulkOperations}.
|
||||
*
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
@@ -278,7 +278,7 @@ public class DefaultBulkOperationsIntegrationTests {
|
||||
private BulkOperations createBulkOps(BulkMode mode, Class<?> entityType) {
|
||||
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = entityType != null
|
||||
? operations.getConverter().getMappingContext().getPersistentEntity(entityType) : Optional.empty();
|
||||
? Optional.of(operations.getConverter().getMappingContext().getPersistentEntity(entityType)) : Optional.empty();
|
||||
|
||||
BulkOperationContext bulkOperationContext = new BulkOperationContext(mode, entity,
|
||||
new QueryMapper(operations.getConverter()), new UpdateMapper(operations.getConverter()));
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.Before;
|
||||
@@ -80,8 +81,9 @@ public class DefaultBulkOperationsUnitTests {
|
||||
when(template.getCollection(anyString())).thenReturn(collection);
|
||||
|
||||
ops = new DefaultBulkOperations(template, "collection-1",
|
||||
new BulkOperationContext(BulkMode.ORDERED, mappingContext.getPersistentEntity(SomeDomainType.class),
|
||||
new QueryMapper(converter), new UpdateMapper(converter)));
|
||||
new BulkOperationContext(BulkMode.ORDERED,
|
||||
Optional.of(mappingContext.getPersistentEntity(SomeDomainType.class)), new QueryMapper(converter),
|
||||
new UpdateMapper(converter)));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1518
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.convert.AbstractMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
@@ -210,7 +211,7 @@ public abstract class MongoOperationsUnitTests {
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.findAll(Object.class);
|
||||
}
|
||||
}.assertException(IllegalArgumentException.class);
|
||||
}.assertException(MappingException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
||||
@@ -1498,7 +1498,7 @@ public class MongoTemplateTests {
|
||||
template.save(map, "maps");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATAMONGO-549
|
||||
@Test(expected = MappingException.class) // DATAMONGO-549, DATAMONGO-1730
|
||||
public void savesMongoPrimitiveObjectCorrectly() {
|
||||
template.save(new Object(), "collection");
|
||||
}
|
||||
@@ -1517,7 +1517,7 @@ public class MongoTemplateTests {
|
||||
assertThat(document.containsKey("_id"), is(true));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATAMONGO-550
|
||||
@Test(expected = MappingException.class) // DATAMONGO-550, DATAMONGO-1730
|
||||
public void rejectsPlainObjectWithOutExplicitCollection() {
|
||||
|
||||
org.bson.Document document = new org.bson.Document("foo", "bar");
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.geo.Metrics;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.core.MongoTemplateTests.PersonWithConvertedId;
|
||||
import org.springframework.data.mongodb.core.MongoTemplateTests.VersionedPerson;
|
||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
|
||||
@@ -86,6 +86,7 @@ public class ReactiveMongoTemplateTests {
|
||||
|
||||
StepVerifier
|
||||
.create(template.dropCollection("people") //
|
||||
.mergeWith(template.dropCollection("personX")) //
|
||||
.mergeWith(template.dropCollection("collection")) //
|
||||
.mergeWith(template.dropCollection(Person.class)) //
|
||||
.mergeWith(template.dropCollection(Venue.class)) //
|
||||
@@ -536,11 +537,11 @@ public class ReactiveMongoTemplateTests {
|
||||
StepVerifier.create(template.save(map, "maps")).expectNextCount(1).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1444
|
||||
@Test // DATAMONGO-1444, DATAMONGO-1730
|
||||
public void savesMongoPrimitiveObjectCorrectly() {
|
||||
|
||||
StepVerifier.create(template.save(new Object(), "collection")) //
|
||||
.expectError(IllegalArgumentException.class) //
|
||||
.expectError(MappingException.class) //
|
||||
.verify();
|
||||
}
|
||||
|
||||
@@ -554,7 +555,7 @@ public class ReactiveMongoTemplateTests {
|
||||
assertThat(dbObject.containsKey("_id"), is(true));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATAMONGO-1444
|
||||
@Test(expected = MappingException.class) // DATAMONGO-1444, DATAMONGO-1730
|
||||
public void rejectsPlainObjectWithOutExplicitCollection() {
|
||||
|
||||
Document dbObject = new Document("foo", "bar");
|
||||
@@ -562,9 +563,8 @@ public class ReactiveMongoTemplateTests {
|
||||
StepVerifier.create(template.save(dbObject, "collection")).expectNextCount(1).verifyComplete();
|
||||
|
||||
StepVerifier.create(template.findById(dbObject.get("_id"), Document.class)) //
|
||||
.expectError(IllegalArgumentException.class) //
|
||||
.expectError(MappingException.class) //
|
||||
.verify();
|
||||
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1444
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.geo.Metrics;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.Venue;
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -68,6 +69,7 @@ import com.mongodb.client.MongoDatabase;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DbRefMappingMongoConverterUnitTests {
|
||||
@@ -483,7 +485,7 @@ public class DbRefMappingMongoConverterUnitTests {
|
||||
|
||||
PersistentPropertyAccessor accessor = propertyEntity.getPropertyAccessor(result.dbRefToConcreteType);
|
||||
MongoPersistentProperty idProperty = mappingContext.getRequiredPersistentEntity(LazyDbRefTarget.class)
|
||||
.getIdProperty().get();
|
||||
.getIdProperty();
|
||||
|
||||
assertThat(accessor.getProperty(idProperty), is(notNullValue()));
|
||||
assertProxyIsResolved(result.dbRefToConcreteType, false);
|
||||
|
||||
@@ -21,7 +21,6 @@ import static org.junit.Assert.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.Before;
|
||||
@@ -33,7 +32,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultMongoTypeMapper}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultMongoTypeMapperUnitTests {
|
||||
@@ -187,13 +186,13 @@ public class DefaultMongoTypeMapperUnitTests {
|
||||
|
||||
private void readsTypeFromField(Document document, Class<?> type) {
|
||||
|
||||
Optional<TypeInformation<?>> typeInfo = typeMapper.readType(document);
|
||||
TypeInformation<?> typeInfo = typeMapper.readType(document);
|
||||
|
||||
if (type != null) {
|
||||
assertThat(typeInfo, is(notNullValue()));
|
||||
assertThat(typeInfo.get().getType(), is(typeCompatibleWith(type)));
|
||||
assertThat(typeInfo.getType(), is(typeCompatibleWith(type)));
|
||||
} else {
|
||||
assertThat(typeInfo, is(Optional.empty()));
|
||||
assertThat(typeInfo, is(nullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ import org.springframework.data.geo.Metrics;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.geo.Polygon;
|
||||
import org.springframework.data.geo.Shape;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.model.MappingInstantiationException;
|
||||
import org.springframework.data.mongodb.core.DocumentTestUtils;
|
||||
import org.springframework.data.mongodb.core.convert.DocumentAccessorUnitTests.NestedType;
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
@@ -462,7 +461,7 @@ public class QueryMapperUnitTests {
|
||||
public void queryMapperShouldNotChangeStateInGivenQueryObjectWhenIdConstrainedByInList() {
|
||||
|
||||
BasicMongoPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(Sample.class);
|
||||
String idPropertyName = persistentEntity.getIdProperty().get().getName();
|
||||
String idPropertyName = persistentEntity.getIdProperty().getName();
|
||||
org.bson.Document queryObject = query(where(idPropertyName).in("42")).getQueryObject();
|
||||
|
||||
Object idValuesBefore = getAsDocument(queryObject, idPropertyName).get("$in");
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.DocumentTestUtils;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.AbstractMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -34,16 +33,17 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoMappingContext}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoMappingContextUnitTests {
|
||||
@@ -65,14 +65,14 @@ public class MongoMappingContextUnitTests {
|
||||
public void doesNotReturnPersistentEntityForMongoSimpleType() {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
assertThat(context.getPersistentEntity(DBRef.class), is(Optional.empty()));
|
||||
assertThat(context.getPersistentEntity(DBRef.class), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-638
|
||||
public void doesNotCreatePersistentEntityForAbstractMap() {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
assertThat(context.getPersistentEntity(AbstractMap.class), is(Optional.empty()));
|
||||
assertThat(context.getPersistentEntity(AbstractMap.class), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-607
|
||||
|
||||
@@ -22,18 +22,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -107,9 +96,9 @@ public class ReactivePerformanceTests {
|
||||
|
||||
converter = new MappingMongoConverter(new DbRefResolver() {
|
||||
@Override
|
||||
public Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref,
|
||||
public Object resolveDbRef(MongoPersistentProperty property, DBRef dbref,
|
||||
DbRefResolverCallback callback, DbRefProxyHandler proxyHandler) {
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,13 +20,10 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.hamcrest.core.Is;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -81,7 +78,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
public void setUp() {
|
||||
|
||||
doReturn("persons").when(persitentEntityMock).getCollection();
|
||||
doReturn(Optional.of(persitentEntityMock)).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class));
|
||||
doReturn(persitentEntityMock).when(mappingContextMock).getPersistentEntity(Mockito.any(Class.class));
|
||||
doReturn(persitentEntityMock).when(mappingContextMock).getRequiredPersistentEntity(Mockito.any(Class.class));
|
||||
doReturn(Person.class).when(persitentEntityMock).getType();
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -389,8 +388,8 @@ public class SimpleMongoRepositoryTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getId(Person entity) {
|
||||
return Optional.ofNullable(entity.getId());
|
||||
public String getId(Person entity) {
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user