Browse Source

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
3.1.x
Mark Paluch 4 years ago committed by Christoph Strobl
parent
commit
6b394e4da6
  1. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java
  2. 47
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java

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

@ -696,7 +696,8 @@ public class QueryMapper {
@Nullable @Nullable
private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) { 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; return value;
} }

47
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.bson.types.ObjectId;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; 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.core.convert.converter.Converter;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@ -45,7 +40,6 @@ import org.springframework.data.convert.WritingConverter;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Point; import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.DocumentTestUtils;
import org.springframework.data.mongodb.core.Person; import org.springframework.data.mongodb.core.Person;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
@ -55,6 +49,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.FieldType; import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.mapping.MongoId;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.mapping.TextScore;
@ -77,22 +72,21 @@ import com.mongodb.client.model.Filters;
* @author Mark Paluch * @author Mark Paluch
* @author David Julia * @author David Julia
*/ */
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class QueryMapperUnitTests { public class QueryMapperUnitTests {
private QueryMapper mapper; private QueryMapper mapper;
private MongoMappingContext context; private MongoMappingContext context;
private MappingMongoConverter converter; private MappingMongoConverter converter;
@Mock MongoDatabaseFactory factory;
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
MongoCustomConversions conversions = new MongoCustomConversions();
this.context = new MongoMappingContext(); 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.converter.afterPropertiesSet();
this.mapper = new QueryMapper(converter); this.mapper = new QueryMapper(converter);
@ -1152,6 +1146,25 @@ public class QueryMapperUnitTests {
.isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive")); .isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
} }
@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 { class WithDeepArrayNesting {
List<WithNestedArray> level0; List<WithNestedArray> level0;
@ -1215,6 +1228,18 @@ public class QueryMapperUnitTests {
@Id private String foo; @Id private String foo;
} }
class WithStringId {
@MongoId String id;
String name;
}
class WithExplicitStringId {
@MongoId(FieldType.STRING) String id;
String name;
}
class BigIntegerId { class BigIntegerId {
@Id private BigInteger id; @Id private BigInteger id;

Loading…
Cancel
Save