From c3259e395c8b9e2f89730abc19c79512377a69e5 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 | 39 ++++++++++++++----- 2 files changed, 31 insertions(+), 11 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 8b0e95748..d8c75b2eb 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 @@ -772,7 +772,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 bc04be336..48cab6e7f 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,11 +33,6 @@ 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.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; @@ -79,22 +74,21 @@ import com.mongodb.client.model.Filters; * @author Mark Paluch * @author David Julia */ -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) public class QueryMapperUnitTests { private QueryMapper mapper; private MongoMappingContext context; private MappingMongoConverter converter; - @Mock MongoDatabaseFactory factory; - @BeforeEach void beforeEach() { + MongoCustomConversions conversions = new MongoCustomConversions(); this.context = new MongoMappingContext(); + this.context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); - this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context); + this.converter.setCustomConversions(conversions); this.converter.afterPropertiesSet(); this.mapper = new QueryMapper(converter); @@ -1333,6 +1327,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; @@ -1402,6 +1415,12 @@ public class QueryMapperUnitTests { String name; } + class WithExplicitStringId { + + @MongoId(FieldType.STRING) String id; + String name; + } + class BigIntegerId { @Id private BigInteger id;