Skip to content

Commit 6b394e4

Browse files
mp911dechristophstrobl
authored andcommitted
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
1 parent 7007f48 commit 6b394e4

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,8 @@ protected boolean isKeyword(String candidate) {
696696
@Nullable
697697
private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) {
698698

699-
if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()) {
699+
if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()
700+
|| value instanceof Document || value instanceof DBObject) {
700701
return value;
701702
}
702703

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

+36-11
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,13 @@
3333
import org.bson.types.ObjectId;
3434
import org.junit.jupiter.api.BeforeEach;
3535
import org.junit.jupiter.api.Test;
36-
import org.junit.jupiter.api.extension.ExtendWith;
37-
import org.mockito.Mock;
38-
import org.mockito.junit.jupiter.MockitoExtension;
39-
import org.mockito.junit.jupiter.MockitoSettings;
40-
import org.mockito.quality.Strictness;
4136

4237
import org.springframework.core.convert.converter.Converter;
4338
import org.springframework.data.annotation.Id;
4439
import org.springframework.data.convert.WritingConverter;
4540
import org.springframework.data.domain.Sort;
4641
import org.springframework.data.domain.Sort.Direction;
4742
import org.springframework.data.geo.Point;
48-
import org.springframework.data.mongodb.MongoDatabaseFactory;
4943
import org.springframework.data.mongodb.core.DocumentTestUtils;
5044
import org.springframework.data.mongodb.core.Person;
5145
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
@@ -55,6 +49,7 @@
5549
import org.springframework.data.mongodb.core.mapping.Document;
5650
import org.springframework.data.mongodb.core.mapping.Field;
5751
import org.springframework.data.mongodb.core.mapping.FieldType;
52+
import org.springframework.data.mongodb.core.mapping.MongoId;
5853
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
5954
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
6055
import org.springframework.data.mongodb.core.mapping.TextScore;
@@ -77,22 +72,21 @@
7772
* @author Mark Paluch
7873
* @author David Julia
7974
*/
80-
@ExtendWith(MockitoExtension.class)
81-
@MockitoSettings(strictness = Strictness.LENIENT)
8275
public class QueryMapperUnitTests {
8376

8477
private QueryMapper mapper;
8578
private MongoMappingContext context;
8679
private MappingMongoConverter converter;
8780

88-
@Mock MongoDatabaseFactory factory;
89-
9081
@BeforeEach
9182
void beforeEach() {
9283

84+
MongoCustomConversions conversions = new MongoCustomConversions();
9385
this.context = new MongoMappingContext();
86+
this.context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
9487

95-
this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context);
88+
this.converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context);
89+
this.converter.setCustomConversions(conversions);
9690
this.converter.afterPropertiesSet();
9791

9892
this.mapper = new QueryMapper(converter);
@@ -1152,6 +1146,25 @@ void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() {
11521146
.isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
11531147
}
11541148

1149+
@Test // GH-3783
1150+
void retainsId$InWithStringArray() {
1151+
1152+
org.bson.Document mappedQuery = mapper.getMappedObject(
1153+
org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"),
1154+
context.getPersistentEntity(WithExplicitStringId.class));
1155+
assertThat(mappedQuery.get("_id")).isEqualTo(org.bson.Document.parse("{ $in: [\"5b8bedceb1e0bfc07b008828\"]}"));
1156+
}
1157+
1158+
@Test // GH-3783
1159+
void mapsId$InInToObjectIds() {
1160+
1161+
org.bson.Document mappedQuery = mapper.getMappedObject(
1162+
org.bson.Document.parse("{ _id : { $in: [\"5b8bedceb1e0bfc07b008828\"]}}"),
1163+
context.getPersistentEntity(ClassWithDefaultId.class));
1164+
assertThat(mappedQuery.get("_id"))
1165+
.isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}"));
1166+
}
1167+
11551168
class WithDeepArrayNesting {
11561169

11571170
List<WithNestedArray> level0;
@@ -1215,6 +1228,18 @@ class Sample {
12151228
@Id private String foo;
12161229
}
12171230

1231+
class WithStringId {
1232+
1233+
@MongoId String id;
1234+
String name;
1235+
}
1236+
1237+
class WithExplicitStringId {
1238+
1239+
@MongoId(FieldType.STRING) String id;
1240+
String name;
1241+
}
1242+
12181243
class BigIntegerId {
12191244

12201245
@Id private BigInteger id;

0 commit comments

Comments
 (0)