Browse Source

DATAMONGO-2135 - Default to intermediate List for properties typed to Collection.

We now defensively create a List rather than a LinkedHashSet (which Spring's CollectionFactory.createCollection(…) defaults to) to make sure we're not accidentally dropping values that are considered equal according to their Java class definition.
pull/621/head
Oliver Drotbohm 7 years ago
parent
commit
9a0dad1723
  1. 15
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 24
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

15
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

@ -249,7 +249,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -249,7 +249,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
DocumentAccessor source, SpELExpressionEvaluator evaluator, ObjectPath path) {
AssociationAwareMongoDbPropertyValueProvider provider = new AssociationAwareMongoDbPropertyValueProvider(source,
evaluator, path);
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<>(
@ -288,8 +287,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -288,8 +287,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
// Make sure id property is set before all other properties
Object rawId = readAndPopulateIdentifier(accessor, documentAccessor, entity,
path, evaluator);
Object rawId = readAndPopulateIdentifier(accessor, documentAccessor, entity, path, evaluator);
ObjectPath currentPath = path.push(accessor.getBean(), entity, rawId);
MongoDbPropertyValueProvider valueProvider = new MongoDbPropertyValueProvider(documentAccessor, evaluator,
@ -621,7 +619,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -621,7 +619,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return;
}
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
MongoPersistentEntity<?> entity = valueType.isSubTypeOf(prop.getType())
? mappingContext.getRequiredPersistentEntity(obj.getClass())
: mappingContext.getRequiredPersistentEntity(type);
@ -633,10 +631,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -633,10 +631,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
accessor.put(prop, document);
}
private boolean isSubtype(Class<?> left, Class<?> right) {
return left.isAssignableFrom(right) && !left.equals(right);
}
/**
* Returns given object as {@link Collection}. Will return the {@link Collection} as is if the source is a
* {@link Collection} already, will convert an array into a {@link Collection} or simply create a single element
@ -1013,9 +1007,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1013,9 +1007,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Assert.notNull(targetType, "Target type must not be null!");
Assert.notNull(path, "Object path must not be null!");
Class<?> collectionType = targetType.getType();
collectionType = Collection.class.isAssignableFrom(collectionType) //
? collectionType //
Class<?> collectionType = targetType.isSubTypeOf(Collection.class) //
? targetType.getType() //
: List.class;
TypeInformation<?> componentType = targetType.getComponentType() != null //

24
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

@ -26,6 +26,7 @@ import static org.junit.Assert.fail; @@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.DocumentTestUtils.*;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import java.math.BigDecimal;
@ -1934,6 +1935,18 @@ public class MappingMongoConverterUnitTests { @@ -1934,6 +1935,18 @@ public class MappingMongoConverterUnitTests {
assertThat(converter.convertId(source.toHexString(), Object.class)).isEqualTo(source.toHexString());
}
@Test // DATAMONGO-2135
public void addsEqualObjectsToCollection() {
org.bson.Document itemDocument = new org.bson.Document("itemKey", "123");
org.bson.Document orderDocument = new org.bson.Document("items",
Arrays.asList(itemDocument, itemDocument, itemDocument));
Order order = converter.read(Order.class, orderDocument);
assertThat(order.items).hasSize(3);
}
static class GenericType<T> {
T content;
}
@ -2362,4 +2375,15 @@ public class MappingMongoConverterUnitTests { @@ -2362,4 +2375,15 @@ public class MappingMongoConverterUnitTests {
final @Id String id;
String value;
}
// DATAMONGO-2135
@EqualsAndHashCode // equality check by fields
static class SomeItem {
String itemKey;
}
static class Order {
Collection<SomeItem> items = new ArrayList<>();
}
}

Loading…
Cancel
Save