diff --git a/pom.xml b/pom.xml index aff1afc489..393f2f3b00 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.3.0-SNAPSHOT + 4.3.x-4567-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 34d95eb205..8a3df0ad44 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.3.0-SNAPSHOT + 4.3.x-4567-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 124a6bf5ad..47738c09a4 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.3.0-SNAPSHOT + 4.3.x-4567-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 39fc1a1de9..c0ac69f6ec 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.3.0-SNAPSHOT + 4.3.x-4567-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 30f8e47a09..5c1d137ccd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -617,15 +617,20 @@ protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersisten if (source instanceof Map sourceMap) { - return sourceMap.entrySet().stream().collect(Collectors.toMap( - entry -> ObjectUtils.nullSafeToString(converter.convertToMongoType(entry.getKey())), - entry -> { - if (entry.getValue() instanceof Document document) { - return getMappedObject(document, entity); - } - return delegateConvertToMongoType(entry.getValue(), entity); - } - )); + Map map = new LinkedHashMap<>(sourceMap.size(), 1F); + + sourceMap.entrySet().forEach(it -> { + + String key = ObjectUtils.nullSafeToString(converter.convertToMongoType(it.getKey())); + + if (it.getValue() instanceof Document document) { + map.put(key, getMappedObject(document, entity)); + } else { + map.put(key, delegateConvertToMongoType(it.getValue(), entity)); + } + }); + + return map; } return delegateConvertToMongoType(source, entity); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 88984baa1f..b0d72fd06f 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.TreeMap; import org.bson.conversions.Bson; import org.bson.types.Code; @@ -1517,6 +1518,20 @@ void usesKeyNameWithDotsIfFieldNameTypeIsKey() { assertThat(mappedObject).isEqualTo("{ 'field.name.with.dots' : 'A' }"); } + @Test // GH-4577 + void mappingShouldRetainMapKeyOrder() { + + TreeMap sourceMap = new TreeMap<>(Map.of("test1", "123", "test2", "456")); + + org.bson.Document target = mapper.getMappedObject(query(where("simpleMap").is(sourceMap)).getQueryObject(), + context.getPersistentEntity(WithSimpleMap.class)); + assertThat(target.get("simpleMap", Map.class)).containsExactlyEntriesOf(sourceMap); + } + + class WithSimpleMap { + Map simpleMap; + } + class WithDeepArrayNesting { List level0; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index df1e13aeae..d9c7496138 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -762,6 +762,18 @@ void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration( assertThat(mappedUpdate).doesNotContainKey("$set.concreteMap.jasnah._class"); } + @Test // GH-4567 + void updateShouldAllowNullValuesInMap() { + + Map map = Collections.singletonMap("jasnah", new NestedDocument("kholin")); + + Update update = new Update().set("concreteMap", Collections.singletonMap("jasnah", null)); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithObjectMap.class)); + + assertThat(mappedUpdate).isEqualTo(new Document("$set", new Document("concreteMap", Collections.singletonMap("jasnah", null)))); + } + @Test // DATAMONGO-1250 @SuppressWarnings("unchecked") void mapsUpdateWithBothReadingAndWritingConverterRegistered() {