From f24e8e5361bf02484e20dc7799bc2a13b808873e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 1 Sep 2021 10:39:36 +0200 Subject: [PATCH] Avoid nested Document conversion to primitive types for fields with an explicit write target. We now no longer attempt to convert query Documents into primitive types to avoid e.g. Document to String conversion. Closes: #3783 Original Pull Request: #3797 --- .../mongodb/core/convert/QueryMapper.java | 3 +- .../core/convert/QueryMapperUnitTests.java | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) 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 7a14f07c4..e7deb3823 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 @@ -778,7 +778,8 @@ public class QueryMapper { @Nullable private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { - if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) { + if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget() + || value instanceof Document || value instanceof DBObject) { return value; } 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 efd354b86..808263697 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 @@ -33,8 +33,7 @@ import org.bson.types.Code; import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; @@ -83,9 +82,12 @@ public class QueryMapperUnitTests { @BeforeEach void beforeEach() { + MongoCustomConversions conversions = new MongoCustomConversions(); this.context = new MongoMappingContext(); + this.context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); + this.converter.setCustomConversions(conversions); this.converter.afterPropertiesSet(); this.mapper = new QueryMapper(converter); @@ -1335,6 +1337,25 @@ public class QueryMapperUnitTests { assertThat(mappedFields).containsEntry("_id", 1); } + @Test // GH-3783 + void retainsId$InWithStringArray() { + + org.bson.Document mappedQuery = mapper.getMappedObject( + org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"), + context.getPersistentEntity(WithExplicitStringId.class)); + assertThat(mappedQuery.get("_id")).isEqualTo(org.bson.Document.parse("{ $in: [\"5b8bedceb1e0bfc07b008828\"]}")); + } + + @Test // GH-3783 + void mapsId$InInToObjectIds() { + + org.bson.Document mappedQuery = mapper.getMappedObject( + org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"), + context.getPersistentEntity(ClassWithDefaultId.class)); + assertThat(mappedQuery.get("_id")) + .isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}")); + } + class WithDeepArrayNesting { List level0; @@ -1404,6 +1425,12 @@ public class QueryMapperUnitTests { String name; } + class WithExplicitStringId { + + @MongoId(FieldType.STRING) String id; + String name; + } + class BigIntegerId { @Id private BigInteger id;