Skip to content

Commit 9a0dad1

Browse files
committed
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.
1 parent a4c5682 commit 9a0dad1

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

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

+4-11
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ private <S extends Object> S read(TypeInformation<S> type, @Nullable Bson bson,
249249
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
250250
DocumentAccessor source, SpELExpressionEvaluator evaluator, ObjectPath path) {
251251

252-
253252
AssociationAwareMongoDbPropertyValueProvider provider = new AssociationAwareMongoDbPropertyValueProvider(source,
254253
evaluator, path);
255254
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<>(
@@ -288,8 +287,7 @@ private <S> S populateProperties(MongoPersistentEntity<S> entity, DocumentAccess
288287

289288
// Make sure id property is set before all other properties
290289

291-
Object rawId = readAndPopulateIdentifier(accessor, documentAccessor, entity,
292-
path, evaluator);
290+
Object rawId = readAndPopulateIdentifier(accessor, documentAccessor, entity, path, evaluator);
293291
ObjectPath currentPath = path.push(accessor.getBean(), entity, rawId);
294292

295293
MongoDbPropertyValueProvider valueProvider = new MongoDbPropertyValueProvider(documentAccessor, evaluator,
@@ -621,7 +619,7 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce
621619
return;
622620
}
623621

624-
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
622+
MongoPersistentEntity<?> entity = valueType.isSubTypeOf(prop.getType())
625623
? mappingContext.getRequiredPersistentEntity(obj.getClass())
626624
: mappingContext.getRequiredPersistentEntity(type);
627625

@@ -633,10 +631,6 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce
633631
accessor.put(prop, document);
634632
}
635633

636-
private boolean isSubtype(Class<?> left, Class<?> right) {
637-
return left.isAssignableFrom(right) && !left.equals(right);
638-
}
639-
640634
/**
641635
* Returns given object as {@link Collection}. Will return the {@link Collection} as is if the source is a
642636
* {@link Collection} already, will convert an array into a {@link Collection} or simply create a single element
@@ -1013,9 +1007,8 @@ private Object readCollectionOrArray(TypeInformation<?> targetType, Collection<?
10131007
Assert.notNull(targetType, "Target type must not be null!");
10141008
Assert.notNull(path, "Object path must not be null!");
10151009

1016-
Class<?> collectionType = targetType.getType();
1017-
collectionType = Collection.class.isAssignableFrom(collectionType) //
1018-
? collectionType //
1010+
Class<?> collectionType = targetType.isSubTypeOf(Collection.class) //
1011+
? targetType.getType() //
10191012
: List.class;
10201013

10211014
TypeInformation<?> componentType = targetType.getComponentType() != null //

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

+24
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import static org.mockito.Mockito.*;
2727
import static org.springframework.data.mongodb.core.DocumentTestUtils.*;
2828

29+
import lombok.EqualsAndHashCode;
2930
import lombok.RequiredArgsConstructor;
3031

3132
import java.math.BigDecimal;
@@ -1934,6 +1935,18 @@ public void donNotConvertStringIdThatIsAnObjectIdHexToObjectIdIfTargetIsObject()
19341935
assertThat(converter.convertId(source.toHexString(), Object.class)).isEqualTo(source.toHexString());
19351936
}
19361937

1938+
@Test // DATAMONGO-2135
1939+
public void addsEqualObjectsToCollection() {
1940+
1941+
org.bson.Document itemDocument = new org.bson.Document("itemKey", "123");
1942+
org.bson.Document orderDocument = new org.bson.Document("items",
1943+
Arrays.asList(itemDocument, itemDocument, itemDocument));
1944+
1945+
Order order = converter.read(Order.class, orderDocument);
1946+
1947+
assertThat(order.items).hasSize(3);
1948+
}
1949+
19371950
static class GenericType<T> {
19381951
T content;
19391952
}
@@ -2362,4 +2375,15 @@ static class ImmutableObjectWithIdConstructorPropertyAndNoIdWitherMethod {
23622375
final @Id String id;
23632376
String value;
23642377
}
2378+
2379+
// DATAMONGO-2135
2380+
2381+
@EqualsAndHashCode // equality check by fields
2382+
static class SomeItem {
2383+
String itemKey;
2384+
}
2385+
2386+
static class Order {
2387+
Collection<SomeItem> items = new ArrayList<>();
2388+
}
23652389
}

0 commit comments

Comments
 (0)