DATAMONGO-1609 - Hacking.
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -31,6 +31,7 @@
|
||||
<springdata.commons>2.0.0.BUILD-SNAPSHOT</springdata.commons>
|
||||
<mongo>3.2.2</mongo>
|
||||
<mongo.reactivestreams>1.2.0</mongo.reactivestreams>
|
||||
<mockito>2.2.17</mockito>
|
||||
</properties>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -17,6 +17,7 @@ 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.*;
|
||||
@@ -94,6 +95,8 @@ 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.CloseableIterator;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.jca.cci.core.ConnectionCallback;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -355,7 +358,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
public CloseableIterator<T> doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityType);
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entityType);
|
||||
|
||||
Document mappedFields = queryMapper.getMappedFields(query.getFieldsObject(), persistentEntity);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), persistentEntity);
|
||||
@@ -441,7 +444,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
|
||||
Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), null);
|
||||
Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), Optional.empty());
|
||||
Document sortObject = query.getSortObject();
|
||||
Document fieldsObject = query.getFieldsObject();
|
||||
|
||||
@@ -633,9 +636,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
String idKey = idProperty == null ? ID_FIELD : idProperty.getName();
|
||||
|
||||
String idKey = mappingContext.getPersistentEntity(entityClass)//
|
||||
.flatMap(it -> it.getIdProperty())//
|
||||
.map(it -> it.getName()).orElse(ID_FIELD);
|
||||
|
||||
return doFindOne(collectionName, new Document(idKey, id), null, entityClass);
|
||||
}
|
||||
|
||||
@@ -755,13 +760,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
final Document document = query == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
Optional.ofNullable(entityClass).flatMap(it -> mappingContext.getPersistentEntity(entityClass)));
|
||||
|
||||
return execute(collectionName, new CollectionCallback<Long>() {
|
||||
public Long doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
|
||||
return collection.count(document);
|
||||
}
|
||||
});
|
||||
return execute(collectionName, (CollectionCallback<Long>) collection -> collection.count(document));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -878,13 +879,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
private void initializeVersionProperty(Object entity) {
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(entity.getClass());
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = getPersistentEntity(entity.getClass());
|
||||
|
||||
if (mongoPersistentEntity != null && mongoPersistentEntity.hasVersionProperty()) {
|
||||
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(
|
||||
mongoPersistentEntity.getPropertyAccessor(entity), mongoConverter.getConversionService());
|
||||
accessor.setProperty(mongoPersistentEntity.getVersionProperty(), 0);
|
||||
}
|
||||
ifAllPresent(persistentEntity, persistentEntity.flatMap(it -> it.getVersionProperty()), (l, r) -> {
|
||||
ConvertingPropertyAccessor accessor = new ConvertingPropertyAccessor(l.getPropertyAccessor(entity),
|
||||
mongoConverter.getConversionService());
|
||||
accessor.setProperty(r, Optional.of(0));
|
||||
});
|
||||
}
|
||||
|
||||
public void insert(Collection<? extends Object> batchToSave, Class<?> entityClass) {
|
||||
@@ -909,11 +910,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
continue;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(element.getClass());
|
||||
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException("No PersistentEntity information found for " + element.getClass());
|
||||
}
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(element.getClass());
|
||||
|
||||
String collection = entity.getCollection();
|
||||
List<T> collectionElements = elementsByCollection.get(collection);
|
||||
@@ -970,35 +967,26 @@ 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!");
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(objectToSave.getClass());
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(objectToSave.getClass());
|
||||
Optional<MongoPersistentProperty> versionProperty = entity.flatMap(it -> it.getVersionProperty());
|
||||
|
||||
// No optimistic locking -> simple save
|
||||
if (mongoPersistentEntity == null || !mongoPersistentEntity.hasVersionProperty()) {
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
return;
|
||||
}
|
||||
|
||||
doSaveVersioned(objectToSave, mongoPersistentEntity, collectionName);
|
||||
mapIfAllPresent(entity, versionProperty, //
|
||||
(l, r) -> doSaveVersioned(objectToSave, l, collectionName))//
|
||||
.orElseGet(() -> doSave(collectionName, objectToSave, this.mongoConverter));
|
||||
}
|
||||
|
||||
private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
|
||||
private <T> T doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
|
||||
|
||||
ConvertingPropertyAccessor convertingAccessor = new ConvertingPropertyAccessor(
|
||||
entity.getPropertyAccessor(objectToSave), mongoConverter.getConversionService());
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
MongoPersistentProperty versionProperty = entity.getVersionProperty();
|
||||
Optional<MongoPersistentProperty> versionProperty = entity.getVersionProperty();
|
||||
Optional<Number> versionNumber = versionProperty.flatMap(it -> convertingAccessor.getProperty(it, Number.class));
|
||||
|
||||
Object version = convertingAccessor.getProperty(versionProperty);
|
||||
Number versionNumber = convertingAccessor.getProperty(versionProperty, Number.class);
|
||||
|
||||
// Fresh instance -> initialize version property
|
||||
if (version == null) {
|
||||
doInsert(collectionName, objectToSave, this.mongoConverter);
|
||||
} else {
|
||||
return mapIfAllPresent(versionProperty, versionNumber, (property, number) -> {
|
||||
|
||||
// Bump version number
|
||||
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
|
||||
convertingAccessor.setProperty(property, Optional.of(number.longValue() + 1));
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
@@ -1011,8 +999,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Update update = Update.fromDocument(document, ID_FIELD);
|
||||
|
||||
// Create query for entity with the id and old version
|
||||
Object id = convertingAccessor.getProperty(idProperty);
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
|
||||
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
|
||||
Object id = convertingAccessor.getProperty(idProperty)
|
||||
.orElseThrow(() -> new IllegalStateException("Required id not found!"));
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(property.getName()).is(number));
|
||||
|
||||
UpdateResult result = doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
|
||||
|
||||
@@ -1022,10 +1012,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
versionNumber, collectionName));
|
||||
}
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, document, collectionName));
|
||||
}
|
||||
|
||||
return objectToSave;
|
||||
|
||||
}).orElseGet(() -> {
|
||||
doInsert(collectionName, objectToSave, this.mongoConverter);
|
||||
return objectToSave;
|
||||
});
|
||||
}
|
||||
|
||||
protected <T> void doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
|
||||
protected <T> T doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
@@ -1037,6 +1033,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
populateIdIfNecessary(objectToSave, id);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
|
||||
return objectToSave;
|
||||
}
|
||||
|
||||
protected Object insertDocument(final String collectionName, final Document document, final Class<?> entityClass) {
|
||||
@@ -1174,7 +1172,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
public UpdateResult doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
|
||||
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = entityClass == null ? null
|
||||
: getPersistentEntity(entityClass);
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
@@ -1210,23 +1209,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
});
|
||||
}
|
||||
|
||||
private void increaseVersionForUpdateIfNecessary(MongoPersistentEntity<?> persistentEntity, Update update) {
|
||||
private void increaseVersionForUpdateIfNecessary(Optional<? extends MongoPersistentEntity<?>> persistentEntity,
|
||||
Update update) {
|
||||
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
String versionFieldName = persistentEntity.getVersionProperty().getFieldName();
|
||||
ifAllPresent(persistentEntity, persistentEntity.flatMap(it -> it.getVersionProperty()), (entity, property) -> {
|
||||
String versionFieldName = property.getFieldName();
|
||||
if (!update.modifies(versionFieldName)) {
|
||||
update.inc(versionFieldName, 1L);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean documentContainsVersionProperty(Document document, MongoPersistentEntity<?> persistentEntity) {
|
||||
private boolean documentContainsVersionProperty(Document document,
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity) {
|
||||
|
||||
if (persistentEntity == null || !persistentEntity.hasVersionProperty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return document.containsKey(persistentEntity.getVersionProperty().getFieldName());
|
||||
return mapIfAllPresent(persistentEntity, persistentEntity.flatMap(it -> it.getVersionProperty()), //
|
||||
(entity, property) -> document.containsKey(property.getFieldName()))//
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
public DeleteResult remove(Object object) {
|
||||
@@ -1256,25 +1255,21 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
private Entry<String, Object> extractIdPropertyAndValue(Object object) {
|
||||
private Pair<String, Optional<Object>> extractIdPropertyAndValue(Object object) {
|
||||
|
||||
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, Optional.ofNullable(((Document) object).get(ID_FIELD)));
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(objectType);
|
||||
MongoPersistentProperty idProp = entity == null ? null : entity.getIdProperty();
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(objectType);
|
||||
return mapIfAllPresent(entity, entity.flatMap(it -> it.getIdProperty()), //
|
||||
|
||||
if (idProp == null || entity == null) {
|
||||
throw new MappingException("No id property found for object of type " + objectType);
|
||||
}
|
||||
|
||||
Object idValue = entity.getPropertyAccessor(object).getProperty(idProp);
|
||||
return Collections.singletonMap(idProp.getFieldName(), idValue).entrySet().iterator().next();
|
||||
(l, r) -> Pair.of(r.getFieldName(), l.getPropertyAccessor(object).getProperty(r)))//
|
||||
.orElseThrow(() -> new MappingException("No id property found for object of type " + objectType));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1285,8 +1280,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
*/
|
||||
private Query getIdQueryFor(Object object) {
|
||||
|
||||
Entry<String, Object> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getKey()).is(id.getValue()));
|
||||
Pair<String, Optional<Object>> id = extractIdPropertyAndValue(object);
|
||||
return new Query(where(id.getFirst()).is(id.getSecond().orElse(null)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1300,34 +1295,38 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.notEmpty(objects, "Cannot create Query for empty collection.");
|
||||
|
||||
Iterator<?> it = objects.iterator();
|
||||
Entry<String, Object> firstEntry = extractIdPropertyAndValue(it.next());
|
||||
Pair<String, Optional<Object>> pair = extractIdPropertyAndValue(it.next());
|
||||
|
||||
ArrayList<Object> ids = new ArrayList<Object>(objects.size());
|
||||
ids.add(firstEntry.getValue());
|
||||
ids.add(pair.getSecond().orElse(null));
|
||||
|
||||
while (it.hasNext()) {
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getValue());
|
||||
ids.add(extractIdPropertyAndValue(it.next()).getSecond().orElse(null));
|
||||
}
|
||||
|
||||
return new Query(where(firstEntry.getKey()).in(ids));
|
||||
return new Query(where(pair.getFirst()).in(ids));
|
||||
}
|
||||
|
||||
private void assertUpdateableIdIfNotSet(Object entity) {
|
||||
private void assertUpdateableIdIfNotSet(Object value) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entity.getClass());
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
Optional<? extends MongoPersistentEntity<?>> persistentEntity = mappingContext
|
||||
.getPersistentEntity(value.getClass());
|
||||
Optional<MongoPersistentProperty> idProperty = persistentEntity.flatMap(it -> it.getIdProperty());
|
||||
|
||||
if (idProperty == null || persistentEntity == null) {
|
||||
return;
|
||||
}
|
||||
Optionals.ifAllPresent(persistentEntity, idProperty, (entity, property) -> {
|
||||
|
||||
Object idValue = persistentEntity.getPropertyAccessor(entity).getProperty(idProperty);
|
||||
Optional<Object> propertyValue = entity.getPropertyAccessor(value).getProperty(property);
|
||||
|
||||
if (idValue == null && !MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(idProperty.getType())) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!", idProperty.getType().getName(),
|
||||
entity.getClass().getName()));
|
||||
}
|
||||
if (propertyValue.isPresent()) {
|
||||
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()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DeleteResult remove(Query query, String collectionName) {
|
||||
@@ -1351,7 +1350,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
final Document queryObject = query.getQueryObject();
|
||||
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
final Optional<? extends MongoPersistentEntity<?>> entity = getPersistentEntity(entityClass);
|
||||
|
||||
return execute(collectionName, new CollectionCallback<DeleteResult>() {
|
||||
public DeleteResult doInCollection(MongoCollection<Document> collection)
|
||||
@@ -1431,7 +1430,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
result = result.sort(query.getSortObject());
|
||||
}
|
||||
|
||||
result = result.filter(queryMapper.getMappedObject(query.getQueryObject(), null));
|
||||
result = result.filter(queryMapper.getMappedObject(query.getQueryObject(), Optional.empty()));
|
||||
}
|
||||
|
||||
if (mapReduceOptions != null) {
|
||||
@@ -1477,7 +1476,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
if (criteria == null) {
|
||||
document.put("cond", null);
|
||||
} else {
|
||||
document.put("cond", queryMapper.getMappedObject(criteria.getCriteriaObject(), null));
|
||||
document.put("cond", queryMapper.getMappedObject(criteria.getCriteriaObject(), Optional.empty()));
|
||||
}
|
||||
// If initial document was a JavaScript string, potentially loaded by Spring's Resource abstraction, load it and
|
||||
// convert to Document
|
||||
@@ -1853,7 +1852,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
*/
|
||||
protected <T> T doFindOne(String collectionName, Document query, Document fields, Class<T> entityClass) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
Document mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
|
||||
|
||||
@@ -1903,7 +1902,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) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
Document mappedFields = queryMapper.getMappedFields(fields, entity);
|
||||
Document mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
@@ -1954,7 +1953,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
serializeToJsonSafely(query), fields, sort, entityClass, collectionName);
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
return executeFindOneInternal(new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort),
|
||||
new ReadDocumentCallback<T>(readerToUse, entityClass, collectionName), collectionName);
|
||||
@@ -1969,7 +1968,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
options = new FindAndModifyOptions();
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
Optional<? extends MongoPersistentEntity<?>> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
@@ -2005,21 +2004,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
|
||||
getIdPropertyFor(savedObject.getClass()).ifPresent(idProp -> {
|
||||
|
||||
if (idProp == null) {
|
||||
return;
|
||||
}
|
||||
ConversionService conversionService = mongoConverter.getConversionService();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(savedObject.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
|
||||
|
||||
ConversionService conversionService = mongoConverter.getConversionService();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(savedObject.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(savedObject);
|
||||
|
||||
if (accessor.getProperty(idProp) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, id);
|
||||
Optional<Object> value = accessor.getProperty(idProp);
|
||||
value.ifPresent(it -> new ConvertingPropertyAccessor(accessor, conversionService).setProperty(idProp, value));
|
||||
});
|
||||
}
|
||||
|
||||
private MongoCollection<Document> getAndPrepareCollection(MongoDatabase db, String collectionName) {
|
||||
@@ -2150,13 +2143,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
return exceptionTranslator;
|
||||
}
|
||||
|
||||
private MongoPersistentEntity<?> getPersistentEntity(Class<?> type) {
|
||||
return type == null ? null : mappingContext.getPersistentEntity(type);
|
||||
private Optional<? extends MongoPersistentEntity<?>> getPersistentEntity(Class<?> type) {
|
||||
return Optional.ofNullable(type).flatMap(it -> mappingContext.getPersistentEntity(it));
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(type);
|
||||
return persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
private Optional<MongoPersistentProperty> getIdPropertyFor(Class<?> type) {
|
||||
return mappingContext.getPersistentEntity(type).flatMap(it -> it.getIdProperty());
|
||||
}
|
||||
|
||||
private <T> String determineEntityCollectionName(T obj) {
|
||||
@@ -2174,12 +2166,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
"No class parameter provided, entity collection can't be determined!");
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No Persistent Entity information found for the class " + entityClass.getName());
|
||||
}
|
||||
return entity.getCollection();
|
||||
return mappingContext.getRequiredPersistentEntity(entityClass).getCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -43,7 +44,6 @@ import org.springframework.data.convert.ThreeTenBackPortConverters;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.data.util.CacheValue;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -71,9 +71,9 @@ public class CustomConversions {
|
||||
|
||||
private final List<Object> converters;
|
||||
|
||||
private final Map<ConvertiblePair, CacheValue<Class<?>>> customReadTargetTypes;
|
||||
private final Map<ConvertiblePair, CacheValue<Class<?>>> customWriteTargetTypes;
|
||||
private final Map<Class<?>, CacheValue<Class<?>>> rawWriteTargetTypes;
|
||||
private final Map<ConvertiblePair, Optional<Class<?>>> customReadTargetTypes;
|
||||
private final Map<ConvertiblePair, Optional<Class<?>>> customWriteTargetTypes;
|
||||
private final Map<Class<?>, Optional<Class<?>>> rawWriteTargetTypes;
|
||||
|
||||
/**
|
||||
* Creates an empty {@link CustomConversions} object.
|
||||
@@ -91,12 +91,12 @@ public class CustomConversions {
|
||||
|
||||
Assert.notNull(converters, "List of converters must not be null!");
|
||||
|
||||
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||
this.customSimpleTypes = new HashSet<Class<?>>();
|
||||
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
|
||||
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
|
||||
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, CacheValue<Class<?>>>();
|
||||
this.readingPairs = new LinkedHashSet<>();
|
||||
this.writingPairs = new LinkedHashSet<>();
|
||||
this.customSimpleTypes = new HashSet<>();
|
||||
this.customReadTargetTypes = new ConcurrentHashMap<>();
|
||||
this.customWriteTargetTypes = new ConcurrentHashMap<>();
|
||||
this.rawWriteTargetTypes = new ConcurrentHashMap<>();
|
||||
|
||||
List<Object> toRegister = new ArrayList<Object>();
|
||||
|
||||
@@ -241,13 +241,8 @@ public class CustomConversions {
|
||||
*/
|
||||
public Class<?> getCustomWriteTarget(final Class<?> sourceType) {
|
||||
|
||||
return getOrCreateAndCache(sourceType, rawWriteTargetTypes, new Producer() {
|
||||
|
||||
@Override
|
||||
public Class<?> get() {
|
||||
return getCustomTarget(sourceType, null, writingPairs);
|
||||
}
|
||||
});
|
||||
return rawWriteTargetTypes.computeIfAbsent(sourceType, it -> getCustomTarget(sourceType, null, writingPairs))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,14 +260,8 @@ public class CustomConversions {
|
||||
return getCustomWriteTarget(sourceType);
|
||||
}
|
||||
|
||||
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customWriteTargetTypes,
|
||||
new Producer() {
|
||||
|
||||
@Override
|
||||
public Class<?> get() {
|
||||
return getCustomTarget(sourceType, requestedTargetType, writingPairs);
|
||||
}
|
||||
});
|
||||
return customWriteTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
|
||||
it -> getCustomTarget(sourceType, requestedTargetType, writingPairs)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,14 +313,8 @@ public class CustomConversions {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customReadTargetTypes,
|
||||
new Producer() {
|
||||
|
||||
@Override
|
||||
public Class<?> get() {
|
||||
return getCustomTarget(sourceType, requestedTargetType, readingPairs);
|
||||
}
|
||||
});
|
||||
return customReadTargetTypes.computeIfAbsent(new ConvertiblePair(sourceType, requestedTargetType),
|
||||
it -> getCustomTarget(sourceType, requestedTargetType, readingPairs)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,54 +326,26 @@ public class CustomConversions {
|
||||
* @param pairs must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static Class<?> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
|
||||
private static Optional<Class<?>> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
|
||||
Collection<ConvertiblePair> pairs) {
|
||||
|
||||
Assert.notNull(sourceType, "Source Class must not be null!");
|
||||
Assert.notNull(pairs, "Collection of ConvertiblePair must not be null!");
|
||||
|
||||
if (requestedTargetType != null && pairs.contains(new ConvertiblePair(sourceType, requestedTargetType))) {
|
||||
return requestedTargetType;
|
||||
return Optional.of(requestedTargetType);
|
||||
}
|
||||
|
||||
for (ConvertiblePair typePair : pairs) {
|
||||
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
|
||||
Class<?> targetType = typePair.getTargetType();
|
||||
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
|
||||
return targetType;
|
||||
return Optional.of(targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to find a value for the given key in the given cache or produce one using the given {@link Producer} and
|
||||
* store it in the cache.
|
||||
*
|
||||
* @param key the key to lookup a potentially existing value, must not be {@literal null}.
|
||||
* @param cache the cache to find the value in, must not be {@literal null}.
|
||||
* @param producer the {@link Producer} to create values to cache, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, CacheValue<Class<?>>> cache, Producer producer) {
|
||||
|
||||
CacheValue<Class<?>> cacheValue = cache.get(key);
|
||||
|
||||
if (cacheValue != null) {
|
||||
return cacheValue.getValue();
|
||||
}
|
||||
|
||||
Class<?> type = producer.get();
|
||||
cache.put(key, CacheValue.<Class<?>> ofNullable(type));
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private interface Producer {
|
||||
|
||||
Class<?> get();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.bson.Document;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
@@ -45,7 +46,7 @@ public interface DbRefResolver {
|
||||
* @param callback will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
Optional<Object> resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
DbRefProxyHandler proxyHandler);
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,8 +61,9 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(property);
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(property);
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty()
|
||||
.orElseThrow(() -> new IllegalStateException("Couldn't find identifier property!"));
|
||||
|
||||
if (idProperty.usePropertyAccess()) {
|
||||
return proxy;
|
||||
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
@@ -84,17 +85,17 @@ 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 Object resolveDbRef(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback,
|
||||
public Optional<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 createLazyLoadingProxy(property, dbref, callback, handler);
|
||||
return Optional.of(createLazyLoadingProxy(property, dbref, callback, handler));
|
||||
}
|
||||
|
||||
return callback.resolve(property);
|
||||
return Optional.ofNullable(callback.resolve(property));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.Document;
|
||||
@@ -26,6 +27,7 @@ import org.springframework.data.convert.DefaultTypeMapper;
|
||||
import org.springframework.data.convert.SimpleTypeInformationMapper;
|
||||
import org.springframework.data.convert.TypeAliasAccessor;
|
||||
import org.springframework.data.convert.TypeInformationMapper;
|
||||
import org.springframework.data.mapping.Alias;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -116,13 +118,13 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
|
||||
accessor.writeTypeTo(result, new Document("$in", restrictedMappedTypes));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected TypeInformation<?> getFallbackTypeFor(Bson source) {
|
||||
|
||||
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
|
||||
protected Optional<TypeInformation<?>> getFallbackTypeFor(Bson source) {
|
||||
return Optional.of(source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,16 +144,16 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
|
||||
*/
|
||||
public Object readAliasFrom(Bson source) {
|
||||
public Alias readAliasFrom(Bson source) {
|
||||
|
||||
if (source instanceof List) {
|
||||
return null;
|
||||
return Alias.NONE;
|
||||
}
|
||||
|
||||
if (source instanceof Document) {
|
||||
return ((Document) source).get(typeKey);
|
||||
return Alias.ofOptional(Optional.ofNullable(((Document) source).get(typeKey)));
|
||||
} else if (source instanceof DBObject) {
|
||||
return ((DBObject) source).get(typeKey);
|
||||
return Alias.ofOptional(Optional.ofNullable(((DBObject) source).get(typeKey)));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot read alias from " + source.getClass());
|
||||
|
||||
@@ -18,6 +18,8 @@ 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;
|
||||
@@ -89,6 +91,15 @@ 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
|
||||
|
||||
@@ -24,6 +24,7 @@ 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;
|
||||
@@ -34,7 +35,6 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
@@ -224,7 +224,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (typeToUse.isCollectionLike() && bson instanceof List) {
|
||||
return (S) readCollectionOrArray(typeToUse, (List) bson, path);
|
||||
return (S) readCollectionOrArray(typeToUse, (List<?>) bson, path);
|
||||
}
|
||||
|
||||
if (typeToUse.isMap()) {
|
||||
@@ -239,13 +239,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return (S) bson;
|
||||
}
|
||||
// Retrieve persistent entity info
|
||||
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext
|
||||
.getPersistentEntity(typeToUse);
|
||||
if (persistentEntity == null) {
|
||||
throw new MappingException("No mapping metadata found for " + rawType.getName());
|
||||
}
|
||||
|
||||
return read(persistentEntity, bson, path);
|
||||
return read((MongoPersistentEntity<S>) mappingContext.getRequiredPersistentEntity(typeToUse), (Document) bson,
|
||||
path);
|
||||
}
|
||||
|
||||
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
|
||||
@@ -259,7 +255,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
path);
|
||||
}
|
||||
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final Bson bson, final ObjectPath path) {
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final Document bson, final ObjectPath path) {
|
||||
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
|
||||
|
||||
@@ -270,19 +266,21 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
|
||||
conversionService);
|
||||
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
final Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
final S result = instance;
|
||||
|
||||
// make sure id property is set before all other properties
|
||||
Object idValue = null;
|
||||
DocumentAccessor documentAccessor = new DocumentAccessor(bson);
|
||||
|
||||
if (idProperty != null && documentAccessor.hasValue(idProperty)) {
|
||||
idValue = getValueInternal(idProperty, bson, evaluator, path);
|
||||
accessor.setProperty(idProperty, idValue);
|
||||
}
|
||||
// make sure id property is set before all other properties
|
||||
Object idValue = idProperty.filter(it -> documentAccessor.hasValue(it)).map(it -> {
|
||||
|
||||
final ObjectPath currentPath = path.push(result, entity, idValue != null ? documentAccessor.get(idProperty) : null);
|
||||
Optional<Object> value = getValueInternal(it, bson, evaluator, path);
|
||||
accessor.setProperty(it, value);
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
final ObjectPath currentPath = path.push(result, entity,
|
||||
idValue != null ? idProperty.map(it -> bson.get(it.getFieldName())).orElse(null) : null);
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
@@ -364,7 +362,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;
|
||||
|
||||
writeInternal(target, bson, type);
|
||||
writeInternal(target, bson, Optional.of(type));
|
||||
if (asMap(bson).containsKey("_is") && asMap(bson).get("_id") == null) {
|
||||
removeFromMap(bson, "_id");
|
||||
}
|
||||
@@ -382,7 +380,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param bson
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeInternal(final Object obj, final Bson bson, final TypeInformation<?> typeHint) {
|
||||
protected void writeInternal(final Object obj, final Bson bson, final Optional<TypeInformation<?>> typeHint) {
|
||||
|
||||
if (null == obj) {
|
||||
return;
|
||||
@@ -403,11 +401,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(entityType)) {
|
||||
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (List) bson);
|
||||
writeCollectionInternal((Collection<?>) obj, Optional.of(ClassTypeInformation.LIST), (BasicDBList) bson);
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(entityType);
|
||||
writeInternal(obj, bson, entity);
|
||||
addCustomTypeKeyIfNecessary(typeHint, obj, bson);
|
||||
}
|
||||
@@ -423,34 +421,28 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
DocumentAccessor dbObjectAccessor = new DocumentAccessor(bson);
|
||||
|
||||
if (!asMap(bson).containsKey("_id") && null != idProperty) {
|
||||
|
||||
try {
|
||||
Object id = accessor.getProperty(idProperty);
|
||||
addToMap(bson, "_id", idMapper.convertId(id));
|
||||
} catch (ConversionException ignored) {}
|
||||
}
|
||||
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
idProperty.ifPresent(
|
||||
prop -> dbObjectAccessor.computeIfAbsent(prop, () -> idMapper.convertId(accessor.getProperty(prop))));
|
||||
|
||||
// Write the properties
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||
|
||||
if (prop.equals(idProperty) || !prop.isWritable()) {
|
||||
if (idProperty.map(it -> it.equals(prop)).orElse(false) || !prop.isWritable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object propertyObj = accessor.getProperty(prop);
|
||||
accessor.getProperty(prop).ifPresent(it -> {
|
||||
if (!conversions.isSimpleType(it.getClass())) {
|
||||
|
||||
if (null != propertyObj) {
|
||||
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
writePropertyInternal(propertyObj, bson, prop);
|
||||
writePropertyInternal(it, bson, prop);
|
||||
} else {
|
||||
writeSimpleInternal(propertyObj, bson, prop);
|
||||
writeSimpleInternal(it, bson, prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -459,11 +451,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
Object propertyObj = accessor.getProperty(inverseProp);
|
||||
|
||||
if (null != propertyObj) {
|
||||
writePropertyInternal(propertyObj, bson, inverseProp);
|
||||
}
|
||||
accessor.getProperty(inverseProp).ifPresent(it -> writePropertyInternal(it, bson, inverseProp));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -481,7 +469,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (valueType.isCollectionLike()) {
|
||||
List collectionInternal = createCollection(asCollection(obj), prop);
|
||||
List<Object> collectionInternal = createCollection(asCollection(obj), prop);
|
||||
accessor.put(prop, collectionInternal);
|
||||
return;
|
||||
}
|
||||
@@ -531,10 +519,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
|
||||
|
||||
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
|
||||
? mappingContext.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
|
||||
? mappingContext.getRequiredPersistentEntity(obj.getClass()) : mappingContext.getRequiredPersistentEntity(type);
|
||||
|
||||
writeInternal(obj, document, entity);
|
||||
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, document);
|
||||
addCustomTypeKeyIfNecessary(Optional.of(ClassTypeInformation.from(prop.getRawType())), obj, document);
|
||||
accessor.put(prop, document);
|
||||
}
|
||||
|
||||
@@ -569,7 +557,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
protected List<Object> createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
||||
|
||||
if (!property.isDbReference()) {
|
||||
return writeCollectionInternal(collection, property.getTypeInformation(), new ArrayList());
|
||||
return writeCollectionInternal(collection, Optional.of(property.getTypeInformation()), new BasicDBList());
|
||||
}
|
||||
|
||||
List<Object> dbList = new ArrayList<Object>();
|
||||
@@ -631,9 +619,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param sink the {@link BasicDBList} to write to.
|
||||
* @return
|
||||
*/
|
||||
private List writeCollectionInternal(Collection<?> source, TypeInformation<?> type, List sink) {
|
||||
private BasicDBList writeCollectionInternal(Collection<?> source, Optional<TypeInformation<?>> type,
|
||||
BasicDBList sink) {
|
||||
|
||||
TypeInformation<?> componentType = type == null ? null : type.getComponentType();
|
||||
Optional<TypeInformation<?>> componentType = type.flatMap(it -> it.getComponentType());
|
||||
|
||||
for (Object element : source) {
|
||||
|
||||
@@ -678,8 +667,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
|
||||
} else {
|
||||
Document document = new Document();
|
||||
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: ClassTypeInformation.OBJECT;
|
||||
Optional<TypeInformation<?>> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: Optional.of(ClassTypeInformation.OBJECT);
|
||||
writeInternal(val, document, valueTypeInfo);
|
||||
addToMap(bson, simpleKey, document);
|
||||
}
|
||||
@@ -765,10 +754,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param value must not be {@literal null}.
|
||||
* @param bson must not be {@literal null}.
|
||||
*/
|
||||
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, Bson bson) {
|
||||
protected void addCustomTypeKeyIfNecessary(Optional<TypeInformation<?>> type, Object value, Bson bson) {
|
||||
|
||||
TypeInformation<?> actualType = type != null ? type.getActualType() : null;
|
||||
Class<?> reference = actualType == null ? Object.class : actualType.getType();
|
||||
Optional<Class<?>> actualType = type.map(it -> it.getActualType()).map(it -> it.getType());
|
||||
Class<?> reference = actualType.orElse(Object.class);
|
||||
Class<?> valueType = ClassUtils.getUserClass(value.getClass());
|
||||
|
||||
boolean notTheSameClass = !valueType.equals(reference);
|
||||
@@ -857,34 +846,30 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return (DBRef) target;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
targetEntity = targetEntity == null ? targetEntity = mappingContext.getPersistentEntity(property) : targetEntity;
|
||||
Optional<? extends MongoPersistentEntity<?>> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
targetEntity = targetEntity.isPresent() ? targetEntity : mappingContext.getPersistentEntity(property);
|
||||
|
||||
if (null == targetEntity) {
|
||||
throw new MappingException("No mapping metadata found for " + target.getClass());
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProperty = targetEntity.getIdProperty();
|
||||
MongoPersistentEntity<?> entity = targetEntity
|
||||
.orElseThrow(() -> new MappingException("No mapping metadata found for " + target.getClass()));
|
||||
|
||||
if (idProperty == null) {
|
||||
throw new MappingException("No id property found on class " + targetEntity.getType());
|
||||
}
|
||||
Optional<MongoPersistentProperty> idProperty = entity.getIdProperty();
|
||||
|
||||
Object id = null;
|
||||
return idProperty.map(it -> {
|
||||
|
||||
if (target.getClass().equals(idProperty.getType())) {
|
||||
id = target;
|
||||
} else {
|
||||
PersistentPropertyAccessor accessor = targetEntity.getPropertyAccessor(target);
|
||||
id = accessor.getProperty(idProperty);
|
||||
}
|
||||
Object id = target.getClass().equals(it.getType()) ? target : entity.getPropertyAccessor(target).getProperty(it);
|
||||
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
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(), targetEntity,
|
||||
idMapper.convertId(id));
|
||||
return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity,
|
||||
idMapper.convertId(Optional.of(id)));
|
||||
|
||||
}).orElseThrow(() -> new MappingException("No id property found on class " + entity.getType()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -892,7 +877,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 Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
public Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
ObjectPath path) {
|
||||
return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop);
|
||||
}
|
||||
@@ -913,8 +898,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
|
||||
TypeInformation<?> componentType = targetType.getComponentType();
|
||||
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
|
||||
TypeInformation<?> componentType = targetType.getComponentType().orElse(ClassTypeInformation.OBJECT);
|
||||
Class<?> rawComponentType = componentType.getType();
|
||||
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>()
|
||||
@@ -973,21 +958,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Class<?> mapType = typeMapper.readType(bson, type).getType();
|
||||
|
||||
TypeInformation<?> keyType = type.getComponentType();
|
||||
Class<?> rawKeyType = keyType == null ? null : keyType.getType();
|
||||
|
||||
TypeInformation<?> valueType = type.getMapValueType();
|
||||
Class<?> rawValueType = valueType == null ? null : valueType.getType();
|
||||
Optional<TypeInformation<?>> valueType = type.getMapValueType();
|
||||
Class<?> rawKeyType = type.getComponentType().map(it -> it.getType()).orElse(null);
|
||||
Class<?> rawValueType = type.getMapValueType().map(it -> it.getType()).orElse(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, rawValueType, sourceMap, map);
|
||||
bulkReadAndConvertDBRefMapIntoTarget(valueType.orElse(null), rawValueType, sourceMap, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
for (Entry<String, Object> entry : sourceMap.entrySet()) {
|
||||
|
||||
if (typeMapper.isTypeKey(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
@@ -999,19 +983,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
Object value = entry.getValue();
|
||||
TypeInformation<?> defaultedValueType = valueType.orElse(ClassTypeInformation.OBJECT);
|
||||
|
||||
if (value instanceof Document) {
|
||||
map.put(key, read(valueType, (Document) value, path));
|
||||
map.put(key, read(defaultedValueType, (Document) value, path));
|
||||
} else if (value instanceof BasicDBObject) {
|
||||
map.put(key, read(valueType, (BasicDBObject) value, path));
|
||||
map.put(key, read(defaultedValueType, (BasicDBObject) value, path));
|
||||
} else if (value instanceof DBRef) {
|
||||
map.put(key, DBRef.class.equals(rawValueType) ? value
|
||||
: readAndConvertDBRef((DBRef) value, valueType, ObjectPath.ROOT, rawValueType));
|
||||
: readAndConvertDBRef((DBRef) value, defaultedValueType, ObjectPath.ROOT, rawValueType));
|
||||
} else if (value instanceof List) {
|
||||
map.put(key, readCollectionOrArray(valueType, (List) value, path));
|
||||
map.put(key, readCollectionOrArray(valueType.orElse(ClassTypeInformation.LIST), (List) value, path));
|
||||
} else {
|
||||
Class<?> valueClass = valueType == null ? null : valueType.getType();
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, rawValueType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1043,9 +1027,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
((DBObject) bson).put(key, value);
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot add key/value pair to %s. as map. Given Bson must be a Document or DBObject!",
|
||||
bson.getClass()));
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot add key/value pair to %s. as map. Given Bson must be a Document or DBObject!", bson.getClass()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1061,8 +1044,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot add all to %s. Given Bson must be a Document or DBObject.", bson.getClass()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot add all to %s. Given Bson must be a Document or DBObject.", bson.getClass()));
|
||||
}
|
||||
|
||||
private void removeFromMap(Bson bson, String key) {
|
||||
@@ -1105,10 +1088,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
TypeInformation<?> typeHint = typeInformation;
|
||||
|
||||
if (obj instanceof List) {
|
||||
return maybeConvertList((List) obj, typeHint);
|
||||
return maybeConvertList((List<Object>) obj, typeHint);
|
||||
}
|
||||
|
||||
if (obj instanceof Document) {
|
||||
|
||||
Document newValueDocument = new Document();
|
||||
for (String vk : ((Document) obj).keySet()) {
|
||||
Object o = ((Document) obj).get(vk);
|
||||
@@ -1118,6 +1102,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (obj instanceof DBObject) {
|
||||
|
||||
Document newValueDbo = new Document();
|
||||
for (String vk : ((DBObject) obj).keySet()) {
|
||||
|
||||
@@ -1130,7 +1115,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
if (obj instanceof Map) {
|
||||
|
||||
Map<Object, Object> converted = new LinkedHashMap<Object, Object>();
|
||||
Document result = new Document();
|
||||
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue(), typeHint));
|
||||
}
|
||||
@@ -1160,9 +1147,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return !obj.getClass().equals(typeInformation.getType()) ? newDocument : removeTypeInfo(newDocument, true);
|
||||
}
|
||||
|
||||
public List maybeConvertList(Iterable<?> source, TypeInformation<?> typeInformation) {
|
||||
public List<Object> maybeConvertList(Iterable<?> source, TypeInformation<?> typeInformation) {
|
||||
|
||||
List<Object> newDbl = new ArrayList<>();
|
||||
|
||||
List newDbl = new ArrayList();
|
||||
for (Object element : source) {
|
||||
newDbl.add(convertToMongoType(element, typeInformation));
|
||||
}
|
||||
@@ -1244,8 +1232,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*/
|
||||
public MongoDbPropertyValueProvider(Bson source, SpELExpressionEvaluator evaluator, ObjectPath path) {
|
||||
|
||||
Assert.notNull(source, "Bson source must not be null!");
|
||||
Assert.notNull(source, "Source document must no be null!");
|
||||
Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null!");
|
||||
Assert.notNull(path, "ObjectPath must not be null!");
|
||||
|
||||
this.source = new DocumentAccessor(source);
|
||||
this.evaluator = evaluator;
|
||||
@@ -1256,16 +1245,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||
public <T> Optional<T> getPropertyValue(MongoPersistentProperty property) {
|
||||
return Optional
|
||||
|
||||
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);
|
||||
.ofNullable(property.getSpelExpression()//
|
||||
.map(it -> evaluator.evaluate(it))//
|
||||
.orElseGet(() -> source.get(property)))//
|
||||
.map(it -> readValue(it, property.getTypeInformation(), path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ 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;
|
||||
@@ -79,7 +80,7 @@ public class MongoExampleMapper {
|
||||
|
||||
Assert.notNull(example, "Example must not be null!");
|
||||
|
||||
return getMappedExample(example, mappingContext.getPersistentEntity(example.getProbeType()));
|
||||
return getMappedExample(example, mappingContext.getRequiredPersistentEntity(example.getProbeType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +91,6 @@ public class MongoExampleMapper {
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Document getMappedExample(Example<?> example, MongoPersistentEntity<?> entity) {
|
||||
|
||||
Assert.notNull(example, "Example must not be null!");
|
||||
@@ -98,9 +98,9 @@ public class MongoExampleMapper {
|
||||
|
||||
Document reference = (Document) converter.convertToMongoType(example.getProbe());
|
||||
|
||||
if (entity.hasIdProperty() && entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {
|
||||
reference.remove(entity.getIdProperty().getFieldName());
|
||||
}
|
||||
Optionals.ifAllPresent(entity.getIdProperty(), //
|
||||
entity.getIdentifierAccessor(example.getProbe()).getIdentifier(), //
|
||||
(property, identifier) -> reference.remove(property.getFieldName()));
|
||||
|
||||
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
|
||||
|
||||
@@ -141,7 +141,7 @@ public class MongoExampleMapper {
|
||||
|
||||
private String getMappedPropertyPath(String path, Class<?> probeType) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(probeType);
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(probeType);
|
||||
|
||||
Iterator<String> parts = Arrays.asList(path.split("\\.")).iterator();
|
||||
|
||||
@@ -151,39 +151,34 @@ public class MongoExampleMapper {
|
||||
|
||||
while (parts.hasNext()) {
|
||||
|
||||
final String part = parts.next();
|
||||
MongoPersistentProperty prop = entity.getPersistentProperty(part);
|
||||
String part = parts.next();
|
||||
MongoPersistentProperty prop = entity.getPersistentProperty(part).orElse(null);
|
||||
|
||||
if (prop == null) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(MongoPersistentProperty property) {
|
||||
|
||||
if (property.getFieldName().equals(part)) {
|
||||
stack.push(property);
|
||||
}
|
||||
entity.doWithProperties((PropertyHandler<MongoPersistentProperty>) property -> {
|
||||
if (property.getFieldName().equals(part)) {
|
||||
stack.push(property);
|
||||
}
|
||||
});
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
prop = stack.pop();
|
||||
}
|
||||
|
||||
resultParts.add(prop.getName());
|
||||
|
||||
if (prop.isEntity() && mappingContext.hasPersistentEntityFor(prop.getActualType())) {
|
||||
entity = mappingContext.getPersistentEntity(prop.getActualType());
|
||||
entity = mappingContext.getRequiredPersistentEntity(prop.getActualType());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.collectionToDelimitedString(resultParts, ".");
|
||||
|
||||
}
|
||||
|
||||
private void applyPropertySpecs(String path, Document source, Class<?> probeType,
|
||||
|
||||
@@ -18,6 +18,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;
|
||||
@@ -115,8 +116,8 @@ class ObjectPath {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Object getCurrentObject() {
|
||||
return items.isEmpty() ? null : items.get(items.size() - 1).getObject();
|
||||
public Optional<Object> getCurrentObject() {
|
||||
return items.isEmpty() ? Optional.empty() : Optional.of(items.get(items.size() - 1).getObject());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.BsonValue;
|
||||
@@ -94,6 +95,10 @@ public class QueryMapper {
|
||||
this.exampleMapper = new MongoExampleMapper(converter);
|
||||
}
|
||||
|
||||
public Document getMappedObject(Bson query, Optional<? extends MongoPersistentEntity<?>> entity) {
|
||||
return getMappedObject(query, entity.orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the property keys used in the given {@link Document} with the appropriate keys by using the
|
||||
* {@link PersistentEntity} metadata.
|
||||
@@ -167,6 +172,10 @@ public class QueryMapper {
|
||||
return mappedSort;
|
||||
}
|
||||
|
||||
public Document getMappedSort(Document sortObject, Optional<? extends MongoPersistentEntity<?>> entity) {
|
||||
return getMappedSort(sortObject, entity.orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps fields to retrieve to the {@link MongoPersistentEntity}s properties. <br />
|
||||
* Also onverts and potentially adds missing property {@code $meta} representation.
|
||||
@@ -183,6 +192,10 @@ public class QueryMapper {
|
||||
return mappedFields.keySet().isEmpty() ? null : mappedFields;
|
||||
}
|
||||
|
||||
public Document getMappedFields(Document fieldsObject, Optional<? extends MongoPersistentEntity<?>> entity) {
|
||||
return getMappedFields(fieldsObject, entity.orElse(null));
|
||||
}
|
||||
|
||||
private void mapMetaAttributes(Document source, MongoPersistentEntity<?> entity, MetaMapping metaMapping) {
|
||||
|
||||
if (entity == null || source == null) {
|
||||
@@ -311,7 +324,7 @@ public class QueryMapper {
|
||||
} else if (valueDbo.containsField("$ne")) {
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
return getMappedObject(resultDbo, null);
|
||||
return getMappedObject(resultDbo, Optional.empty());
|
||||
}
|
||||
return resultDbo;
|
||||
}
|
||||
@@ -330,7 +343,7 @@ public class QueryMapper {
|
||||
} else if (valueDbo.containsKey("$ne")) {
|
||||
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
return getMappedObject(resultDbo, null);
|
||||
return getMappedObject(resultDbo, Optional.empty());
|
||||
}
|
||||
return resultDbo;
|
||||
|
||||
@@ -380,8 +393,8 @@ public class QueryMapper {
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = documentField.getPropertyEntity();
|
||||
return entity.hasIdProperty()
|
||||
&& (type.equals(DBRef.class) || entity.getIdProperty().getActualType().isAssignableFrom(type));
|
||||
return entity.hasIdProperty() && (type.equals(DBRef.class)
|
||||
|| entity.getIdProperty().map(it -> it.getActualType().isAssignableFrom(type)).orElse(false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,28 +537,31 @@ public class QueryMapper {
|
||||
return converter.toDBRef(source, property);
|
||||
}
|
||||
|
||||
private Optional<Object> convertId(Object id) {
|
||||
return convertId(Optional.of(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public Object convertId(Object id) {
|
||||
public Optional<Object> convertId(Optional<Object> id) {
|
||||
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return id.map(it -> {
|
||||
|
||||
if (id instanceof String) {
|
||||
return ObjectId.isValid(id.toString()) ? conversionService.convert(id, ObjectId.class) : id;
|
||||
}
|
||||
if (it instanceof String) {
|
||||
return ObjectId.isValid(it.toString()) ? conversionService.convert(it, ObjectId.class) : it;
|
||||
}
|
||||
|
||||
try {
|
||||
return conversionService.canConvert(id.getClass(), ObjectId.class) ? conversionService.convert(id, ObjectId.class)
|
||||
: delegateConvertToMongoType(id, null);
|
||||
} catch (ConversionException o_O) {
|
||||
return delegateConvertToMongoType(id, null);
|
||||
}
|
||||
try {
|
||||
return conversionService.canConvert(it.getClass(), ObjectId.class)
|
||||
? conversionService.convert(it, ObjectId.class) : delegateConvertToMongoType(it, null);
|
||||
} catch (ConversionException o_O) {
|
||||
return delegateConvertToMongoType(it, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -820,13 +836,9 @@ public class QueryMapper {
|
||||
@Override
|
||||
public boolean isIdField() {
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
return idProperty.getName().equals(name) || idProperty.getFieldName().equals(name);
|
||||
}
|
||||
|
||||
return DEFAULT_ID_NAMES.contains(name);
|
||||
return entity.getIdProperty()//
|
||||
.map(it -> it.getName().equals(name) || it.getFieldName().equals(name))//
|
||||
.orElseGet(() -> DEFAULT_ID_NAMES.contains(name));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -845,7 +857,7 @@ public class QueryMapper {
|
||||
@Override
|
||||
public MongoPersistentEntity<?> getPropertyEntity() {
|
||||
MongoPersistentProperty property = getProperty();
|
||||
return property == null ? null : mappingContext.getPersistentEntity(property);
|
||||
return property == null ? null : mappingContext.getRequiredPersistentEntity(property);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -875,8 +887,11 @@ public class QueryMapper {
|
||||
|
||||
if (this.path != null) {
|
||||
for (MongoPersistentProperty p : this.path) {
|
||||
if (p.isAssociation()) {
|
||||
return p.getAssociation();
|
||||
|
||||
Optional<Association<MongoPersistentProperty>> association = p.getAssociation();
|
||||
|
||||
if (association.isPresent()) {
|
||||
return association.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
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;
|
||||
@@ -38,5 +40,6 @@ interface ValueResolver {
|
||||
* @param parent
|
||||
* @return
|
||||
*/
|
||||
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath parent);
|
||||
Optional<Object> getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
|
||||
ObjectPath path);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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;
|
||||
@@ -53,8 +54,8 @@ import org.springframework.util.StringUtils;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
||||
MongoPersistentEntity<T>, ApplicationContextAware {
|
||||
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty>
|
||||
implements MongoPersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
private static final String AMBIGUOUS_FIELD_MAPPING = "Ambiguous field mapping detected! Both %s and %s map to the same field name %s! Disambiguate using @Field annotation!";
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
@@ -73,24 +74,18 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
*/
|
||||
public BasicMongoPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
super(typeInformation, MongoPersistentPropertyComparator.INSTANCE);
|
||||
super(typeInformation, Optional.of(MongoPersistentPropertyComparator.INSTANCE));
|
||||
|
||||
Class<?> rawType = typeInformation.getType();
|
||||
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
|
||||
|
||||
Document document = this.findAnnotation(Document.class);
|
||||
Optional<Document> document = this.findAnnotation(Document.class);
|
||||
|
||||
this.expression = detectExpression(document);
|
||||
this.expression = document.map(it -> detectExpression(it)).orElse(null);
|
||||
this.context = new StandardEvaluationContext();
|
||||
|
||||
if (document != null) {
|
||||
|
||||
this.collection = StringUtils.hasText(document.collection()) ? document.collection() : fallback;
|
||||
this.language = StringUtils.hasText(document.language()) ? document.language() : "";
|
||||
} else {
|
||||
this.collection = fallback;
|
||||
this.language = "";
|
||||
}
|
||||
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("");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -127,7 +122,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
*/
|
||||
@Override
|
||||
public MongoPersistentProperty getTextScoreProperty() {
|
||||
return getPersistentProperty(TextScore.class);
|
||||
return getPersistentProperty(TextScore.class).orElse(null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -207,40 +202,38 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
return null;
|
||||
}
|
||||
|
||||
MongoPersistentProperty currentIdProperty = getIdProperty();
|
||||
Optional<MongoPersistentProperty> currentIdProperty = getIdProperty();
|
||||
|
||||
boolean currentIdPropertyIsSet = currentIdProperty != null;
|
||||
@SuppressWarnings("null")
|
||||
boolean currentIdPropertyIsExplicit = currentIdPropertyIsSet ? currentIdProperty.isExplicitIdProperty() : false;
|
||||
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
|
||||
return currentIdProperty.map(it -> {
|
||||
|
||||
if (!currentIdPropertyIsSet) {
|
||||
return property;
|
||||
boolean currentIdPropertyIsExplicit = it.isExplicitIdProperty();
|
||||
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
|
||||
Optional<Field> currentIdPropertyField = it.getField();
|
||||
|
||||
}
|
||||
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));
|
||||
|
||||
@SuppressWarnings("null")
|
||||
Field currentIdPropertyField = currentIdProperty.getField();
|
||||
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
|
||||
// explicit id property takes precedence over implicit id property
|
||||
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) {
|
||||
// no id property override - current property is explicitly defined
|
||||
|
||||
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
|
||||
// explicit id property takes precedence over implicit id property
|
||||
return 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));
|
||||
}
|
||||
|
||||
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||
// no id property override - current property is explicitly defined
|
||||
return null;
|
||||
|
||||
} 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));
|
||||
}
|
||||
}).orElse(property);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,8 +267,8 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class AssertFieldNameUniquenessHandler implements PropertyHandler<MongoPersistentProperty>,
|
||||
AssociationHandler<MongoPersistentProperty> {
|
||||
private static class AssertFieldNameUniquenessHandler
|
||||
implements PropertyHandler<MongoPersistentProperty>, AssociationHandler<MongoPersistentProperty> {
|
||||
|
||||
private final Map<String, MongoPersistentProperty> properties = new HashMap<String, MongoPersistentProperty>();
|
||||
|
||||
@@ -293,8 +286,8 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
MongoPersistentProperty existingProperty = properties.get(fieldName);
|
||||
|
||||
if (existingProperty != null) {
|
||||
throw new MappingException(String.format(AMBIGUOUS_FIELD_MAPPING, property.toString(),
|
||||
existingProperty.toString(), fieldName));
|
||||
throw new MappingException(
|
||||
String.format(AMBIGUOUS_FIELD_MAPPING, property.toString(), existingProperty.toString(), fieldName));
|
||||
}
|
||||
|
||||
properties.put(fieldName, property);
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
@@ -29,6 +28,7 @@ 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.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -72,10 +72,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
* @param simpleTypeHolder
|
||||
* @param fieldNamingStrategy
|
||||
*/
|
||||
public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||
public BasicMongoPersistentProperty(Property property, MongoPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
super(property, owner, simpleTypeHolder);
|
||||
this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE
|
||||
: fieldNamingStrategy;
|
||||
|
||||
@@ -120,15 +120,11 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
if (isIdProperty()) {
|
||||
|
||||
if (owner == null) {
|
||||
if (!getOwner().getIdProperty().isPresent()) {
|
||||
return ID_FIELD_NAME;
|
||||
}
|
||||
|
||||
if (owner.getIdProperty() == null) {
|
||||
return ID_FIELD_NAME;
|
||||
}
|
||||
|
||||
if (owner.isIdProperty(this)) {
|
||||
if (getOwner().isIdProperty(this)) {
|
||||
return ID_FIELD_NAME;
|
||||
}
|
||||
}
|
||||
@@ -158,14 +154,13 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
private String getAnnotatedFieldName() {
|
||||
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
|
||||
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
||||
|
||||
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
||||
return annotation.value();
|
||||
}
|
||||
|
||||
return null;
|
||||
return annotation//
|
||||
.filter(it -> StringUtils.hasText(it.value()))//
|
||||
.map(it -> it.value())//
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -173,9 +168,11 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getFieldOrder()
|
||||
*/
|
||||
public int getFieldOrder() {
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
|
||||
|
||||
Optional<org.springframework.data.mongodb.core.mapping.Field> annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
||||
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
|
||||
|
||||
return annotation.map(it -> it.order()).orElse(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -200,7 +197,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef()
|
||||
*/
|
||||
public DBRef getDBRef() {
|
||||
return findAnnotation(DBRef.class);
|
||||
return findAnnotation(DBRef.class).orElse(null);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
/**
|
||||
@@ -43,9 +41,9 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty
|
||||
* @param simpleTypeHolder
|
||||
* @param fieldNamingStrategy
|
||||
*/
|
||||
public CachingMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
public CachingMongoPersistentProperty(Property property, MongoPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||
super(property, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.AbstractMap;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -25,6 +23,7 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@@ -76,9 +75,9 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
||||
* @see org.springframework.data.mapping.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.MutablePersistentEntity, org.springframework.data.mapping.SimpleTypeHolder)
|
||||
*/
|
||||
@Override
|
||||
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
BasicMongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
return new CachingMongoPersistentProperty(field, descriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
public MongoPersistentProperty createPersistentProperty(Property property, BasicMongoPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
return new CachingMongoPersistentProperty(property, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.Document;
|
||||
import org.junit.Test;
|
||||
@@ -28,6 +27,8 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DocumentAccessor}.
|
||||
*
|
||||
@@ -36,8 +37,8 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
public class DocumentAccessorUnitTests {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
MongoPersistentEntity<?> projectingTypeEntity = context.getPersistentEntity(ProjectingType.class);
|
||||
MongoPersistentProperty fooProperty = projectingTypeEntity.getPersistentProperty("foo");
|
||||
MongoPersistentEntity<?> projectingTypeEntity = context.getRequiredPersistentEntity(ProjectingType.class);
|
||||
MongoPersistentProperty fooProperty = projectingTypeEntity.getRequiredPersistentProperty("foo");
|
||||
|
||||
@Test // DATAMONGO-766
|
||||
public void putsNestedFieldCorrectly() {
|
||||
@@ -80,14 +81,14 @@ public class DocumentAccessorUnitTests {
|
||||
@Test // DATAMONGO-1335
|
||||
public void writesAllNestingsCorrectly() {
|
||||
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(TypeWithTwoNestings.class);
|
||||
MongoPersistentEntity<?> entity = context.getRequiredPersistentEntity(TypeWithTwoNestings.class);
|
||||
|
||||
Document target = new Document();
|
||||
|
||||
DocumentAccessor accessor = new DocumentAccessor(target);
|
||||
accessor.put(entity.getPersistentProperty("id"), "id");
|
||||
accessor.put(entity.getPersistentProperty("b"), "b");
|
||||
accessor.put(entity.getPersistentProperty("c"), "c");
|
||||
accessor.put(entity.getRequiredPersistentProperty("id"), "id");
|
||||
accessor.put(entity.getRequiredPersistentProperty("b"), "b");
|
||||
accessor.put(entity.getRequiredPersistentProperty("c"), "c");
|
||||
|
||||
Document nestedA = DocumentTestUtils.getAsDocument(target, "a");
|
||||
|
||||
@@ -100,11 +101,11 @@ public class DocumentAccessorUnitTests {
|
||||
public void exposesAvailabilityOfFields() {
|
||||
|
||||
DocumentAccessor accessor = new DocumentAccessor(new Document("a", new BasicDBObject("c", "d")));
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(ProjectingType.class);
|
||||
MongoPersistentEntity<?> entity = context.getRequiredPersistentEntity(ProjectingType.class);
|
||||
|
||||
assertThat(accessor.hasValue(entity.getPersistentProperty("foo")), is(false));
|
||||
assertThat(accessor.hasValue(entity.getPersistentProperty("a")), is(true));
|
||||
assertThat(accessor.hasValue(entity.getPersistentProperty("name")), is(false));
|
||||
assertThat(accessor.hasValue(entity.getRequiredPersistentProperty("foo")), is(false));
|
||||
assertThat(accessor.hasValue(entity.getRequiredPersistentProperty("a")), is(true));
|
||||
assertThat(accessor.hasValue(entity.getRequiredPersistentProperty("name")), is(false));
|
||||
}
|
||||
|
||||
static class ProjectingType {
|
||||
|
||||
@@ -115,6 +115,8 @@ public class MappingMongoConverterUnitTests {
|
||||
mappingContext.setApplicationContext(context);
|
||||
mappingContext.afterPropertiesSet();
|
||||
|
||||
mappingContext.getPersistentEntity(Address.class);
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.afterPropertiesSet();
|
||||
}
|
||||
@@ -413,7 +415,6 @@ public class MappingMongoConverterUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writesNestedCollectionsCorrectly() {
|
||||
|
||||
CollectionWrapper wrapper = new CollectionWrapper();
|
||||
@@ -495,7 +496,6 @@ public class MappingMongoConverterUnitTests {
|
||||
|
||||
GenericType<?> result = converter.read(GenericType.class, new org.bson.Document("content", address));
|
||||
assertThat(result.content, is(instanceOf(Address.class)));
|
||||
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-228
|
||||
@@ -1134,7 +1134,6 @@ public class MappingMongoConverterUnitTests {
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-724
|
||||
@SuppressWarnings("unchecked")
|
||||
public void mappingConsidersCustomConvertersNotWritingTypeInformation() {
|
||||
|
||||
Person person = new Person();
|
||||
@@ -1345,8 +1344,8 @@ public class MappingMongoConverterUnitTests {
|
||||
|
||||
assertThat(document, is(notNullValue()));
|
||||
assertThat(document.get("box"), is(instanceOf(org.bson.Document.class)));
|
||||
assertThat(document.get("box"), is((Object) new org.bson.Document().append("first", toDocument(object.box.getFirst()))
|
||||
.append("second", toDocument(object.box.getSecond()))));
|
||||
assertThat(document.get("box"), is((Object) new org.bson.Document()
|
||||
.append("first", toDocument(object.box.getFirst())).append("second", toDocument(object.box.getSecond()))));
|
||||
}
|
||||
|
||||
private static org.bson.Document toDocument(Point point) {
|
||||
@@ -1386,7 +1385,7 @@ public class MappingMongoConverterUnitTests {
|
||||
List<org.bson.Document> points = (List<org.bson.Document>) polygonDoc.get("points");
|
||||
|
||||
assertThat(points, hasSize(3));
|
||||
assertThat(points, Matchers.<org.bson.Document> hasItems(toDocument(object.polygon.getPoints().get(0)),
|
||||
assertThat(points, Matchers.<org.bson.Document>hasItems(toDocument(object.polygon.getPoints().get(0)),
|
||||
toDocument(object.polygon.getPoints().get(1)), toDocument(object.polygon.getPoints().get(2))));
|
||||
}
|
||||
|
||||
@@ -1705,12 +1704,11 @@ public class MappingMongoConverterUnitTests {
|
||||
|
||||
TypeWithOptional read = converter.read(TypeWithOptional.class, result);
|
||||
|
||||
assertThat(read.string, is(Optional.<String> empty()));
|
||||
assertThat(read.string, is(Optional.<String>empty()));
|
||||
assertThat(read.localDateTime, is(Optional.of(now)));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1118
|
||||
@SuppressWarnings("unchecked")
|
||||
public void convertsMapKeyUsingCustomConverterForAndBackwards() {
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
|
||||
@@ -80,7 +80,8 @@ public class MongoExampleMapperUnitTests {
|
||||
|
||||
IsBsonObject<Bson> expected = isBsonObject().containing("_id", "steelheart");
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -96,7 +97,8 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue", "firefight").//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -110,7 +112,8 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue", "firefight").//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -124,7 +127,8 @@ public class MongoExampleMapperUnitTests {
|
||||
IsBsonObject<Bson> expected = isBsonObject().//
|
||||
containing("listOfString", list);
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -135,7 +139,8 @@ public class MongoExampleMapperUnitTests {
|
||||
|
||||
IsBsonObject<Bson> expected = isBsonObject().containing("custom_field_name", "Mitosis");
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -146,7 +151,7 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.flatDoc.stringValue = "conflux";
|
||||
|
||||
org.bson.Document document = mapper.getMappedExample(Example.of(probe),
|
||||
context.getPersistentEntity(WrapperDocument.class));
|
||||
context.getRequiredPersistentEntity(WrapperDocument.class));
|
||||
|
||||
assertThat(document,
|
||||
isBsonObject().containing("_class", new org.bson.Document("$in", new String[] { probe.getClass().getName() })));
|
||||
@@ -161,7 +166,8 @@ public class MongoExampleMapperUnitTests {
|
||||
|
||||
IsBsonObject<Bson> expected = isBsonObject().containing("flatDoc\\.stringValue", "conflux");
|
||||
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getPersistentEntity(WrapperDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(WrapperDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -173,7 +179,7 @@ public class MongoExampleMapperUnitTests {
|
||||
|
||||
Example<?> example = Example.of(probe, matching().withIncludeNullValues());
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class)), //
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)), //
|
||||
isBsonObject().containing("flatDoc.stringValue", "conflux"));
|
||||
}
|
||||
|
||||
@@ -190,7 +196,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue.$regex", "^firefight").//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -206,7 +212,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue.$regex", "^" + Pattern.quote("fire.ight")).//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -222,7 +228,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue.$regex", "firefight$").//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -238,7 +244,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue.$regex", "firefight").//
|
||||
containing("custom_field_name.$regex", "^(cat|dog).*shelter\\d?");
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -254,7 +260,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue", new org.bson.Document("$regex", "firefight$").append("$options", "i")).//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -270,7 +276,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue", new org.bson.Document("$regex", Pattern.quote("firefight")).append("$options", "i")).//
|
||||
containing("intValue", 100);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -281,10 +287,11 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.referenceDocument = new ReferenceDocument();
|
||||
probe.referenceDocument.id = "200";
|
||||
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe),
|
||||
context.getRequiredPersistentEntity(WithDBRef.class));
|
||||
com.mongodb.DBRef reference = getTypedValue(document, "referenceDocument", com.mongodb.DBRef.class);
|
||||
|
||||
assertThat(reference.getId(), Is.<Object>is("200"));
|
||||
assertThat(reference.getId(), Is.<Object> is("200"));
|
||||
assertThat(reference.getCollectionName(), is("refDoc"));
|
||||
}
|
||||
|
||||
@@ -294,7 +301,8 @@ public class MongoExampleMapperUnitTests {
|
||||
FlatDocument probe = new FlatDocument();
|
||||
probe.stringValue = "steelheart";
|
||||
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe),
|
||||
context.getRequiredPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(document, isBsonObject().containing("stringValue", "steelheart"));
|
||||
}
|
||||
@@ -305,10 +313,11 @@ public class MongoExampleMapperUnitTests {
|
||||
ClassWithGeoTypes probe = new ClassWithGeoTypes();
|
||||
probe.legacyPoint = new Point(10D, 20D);
|
||||
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe), context.getPersistentEntity(WithDBRef.class));
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe),
|
||||
context.getRequiredPersistentEntity(WithDBRef.class));
|
||||
|
||||
assertThat(document.get("legacyPoint.x"), Is.<Object>is(10D));
|
||||
assertThat(document.get("legacyPoint.y"), Is.<Object>is(20D));
|
||||
assertThat(document.get("legacyPoint.x"), Is.<Object> is(10D));
|
||||
assertThat(document.get("legacyPoint.y"), Is.<Object> is(20D));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -325,7 +334,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue", "string").//
|
||||
containing("intValue", 10);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -342,7 +351,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("custom_field_name", "foo").//
|
||||
containing("intValue", 10);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -360,7 +369,8 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("flatDoc\\.custom_field_name", "foo").//
|
||||
containing("flatDoc\\.intValue", 10);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -378,7 +388,8 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("flatDoc\\.stringValue", "string").//
|
||||
containing("flatDoc\\.intValue", 10);
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(WrapperDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)),
|
||||
is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -394,7 +405,7 @@ public class MongoExampleMapperUnitTests {
|
||||
containing("stringValue.$regex", ".*firefight.*").//
|
||||
containing("custom_field_name", "steelheart");
|
||||
|
||||
assertThat(mapper.getMappedExample(example, context.getPersistentEntity(FlatDocument.class)), is(expected));
|
||||
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1245
|
||||
@@ -405,7 +416,8 @@ public class MongoExampleMapperUnitTests {
|
||||
probe.customNamedField = "steelheart";
|
||||
probe.anotherStringValue = "calamity";
|
||||
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe), context.getPersistentEntity(FlatDocument.class));
|
||||
org.bson.Document document = mapper.getMappedExample(of(probe),
|
||||
context.getRequiredPersistentEntity(FlatDocument.class));
|
||||
|
||||
assertThat(document, isBsonObject().containing("anotherStringValue", "calamity"));
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ 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.model.Property;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -87,7 +88,10 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
@Test // DATAMONGO-553
|
||||
public void usesPropertyAccessForThrowableCause() {
|
||||
|
||||
MongoPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Throwable.class, "cause"));
|
||||
BasicMongoPersistentEntity<Throwable> entity = new BasicMongoPersistentEntity<>(
|
||||
ClassTypeInformation.from(Throwable.class));
|
||||
MongoPersistentProperty property = getPropertyFor(entity, "cause");
|
||||
|
||||
assertThat(property.usePropertyAccess(), is(true));
|
||||
}
|
||||
|
||||
@@ -96,13 +100,13 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
|
||||
Field field = ReflectionUtils.findField(Person.class, "lastname");
|
||||
|
||||
MongoPersistentProperty property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(),
|
||||
UppercaseFieldNamingStrategy.INSTANCE);
|
||||
MongoPersistentProperty property = new BasicMongoPersistentProperty(Property.of(field), entity,
|
||||
new SimpleTypeHolder(), UppercaseFieldNamingStrategy.INSTANCE);
|
||||
assertThat(property.getFieldName(), is("LASTNAME"));
|
||||
|
||||
field = ReflectionUtils.findField(Person.class, "firstname");
|
||||
|
||||
property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(),
|
||||
property = new BasicMongoPersistentProperty(Property.of(field), entity, new SimpleTypeHolder(),
|
||||
UppercaseFieldNamingStrategy.INSTANCE);
|
||||
assertThat(property.getFieldName(), is("foo"));
|
||||
}
|
||||
@@ -111,8 +115,8 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
public void rejectsInvalidValueReturnedByFieldNamingStrategy() {
|
||||
|
||||
Field field = ReflectionUtils.findField(Person.class, "lastname");
|
||||
MongoPersistentProperty property = new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder(),
|
||||
InvalidFieldNamingStrategy.INSTANCE);
|
||||
MongoPersistentProperty property = new BasicMongoPersistentProperty(Property.of(field), entity,
|
||||
new SimpleTypeHolder(), InvalidFieldNamingStrategy.INSTANCE);
|
||||
|
||||
exception.expect(MappingException.class);
|
||||
exception.expectMessage(InvalidFieldNamingStrategy.class.getName());
|
||||
@@ -192,7 +196,7 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getPropertyFor(MongoPersistentEntity<?> persistentEntity, Field field) {
|
||||
return new BasicMongoPersistentProperty(field, null, persistentEntity, new SimpleTypeHolder(),
|
||||
return new BasicMongoPersistentProperty(Property.of(field), persistentEntity, new SimpleTypeHolder(),
|
||||
PropertyNameFieldNamingStrategy.INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user