Skip to content

Commit c2f708a

Browse files
christophstroblmp911de
authored andcommitted
Fix property value conversion for $in clauses.
This commit fixes an issue where a property value converter is not applied if the query is using an $in clause that compares the value against a collection of potential candidates. Closes #4080 Original pull request: #4324
1 parent 7f50fe1 commit c2f708a

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

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

+19-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.springframework.core.convert.ConversionService;
3131
import org.springframework.core.convert.converter.Converter;
3232
import org.springframework.data.annotation.Reference;
33+
import org.springframework.data.convert.PropertyValueConverter;
34+
import org.springframework.data.convert.ValueConversionContext;
3335
import org.springframework.data.domain.Example;
3436
import org.springframework.data.mapping.Association;
3537
import org.springframework.data.mapping.MappingException;
@@ -40,6 +42,7 @@
4042
import org.springframework.data.mapping.PropertyReferenceException;
4143
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
4244
import org.springframework.data.mapping.context.MappingContext;
45+
import org.springframework.data.mapping.model.PropertyValueProvider;
4346
import org.springframework.data.mongodb.MongoExpression;
4447
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
4548
import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext;
@@ -437,9 +440,22 @@ protected Object getMappedValue(Field documentField, Object sourceValue) {
437440

438441
if (documentField.getProperty() != null
439442
&& converter.getCustomConversions().hasValueConverter(documentField.getProperty())) {
440-
return converter.getCustomConversions().getPropertyValueConversions()
441-
.getValueConverter(documentField.getProperty())
442-
.write(value, new MongoConversionContext(null, documentField.getProperty(), converter));
443+
444+
MongoConversionContext conversionContext = new MongoConversionContext(new PropertyValueProvider<>() {
445+
@Override
446+
public <T> T getPropertyValue(MongoPersistentProperty property) {
447+
throw new IllegalStateException("No enclosing property available");
448+
}
449+
}, documentField.getProperty(), converter);
450+
PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter = converter
451+
.getCustomConversions().getPropertyValueConversions().getValueConverter(documentField.getProperty());
452+
453+
/* might be an $in clause with multiple entries */
454+
if (!documentField.getProperty().isCollectionLike() && sourceValue instanceof Collection<?> collection) {
455+
return collection.stream().map(it -> valueConverter.write(it, conversionContext)).collect(Collectors.toList());
456+
}
457+
458+
return valueConverter.write(value, conversionContext);
443459
}
444460

445461
if (documentField.isIdField() && !documentField.isAssociation()) {

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

+13-13
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,7 @@
5151
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
5252
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
5353
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
54-
import org.springframework.data.mongodb.core.mapping.DBRef;
55-
import org.springframework.data.mongodb.core.mapping.Document;
56-
import org.springframework.data.mongodb.core.mapping.DocumentReference;
57-
import org.springframework.data.mongodb.core.mapping.Field;
58-
import org.springframework.data.mongodb.core.mapping.FieldType;
59-
import org.springframework.data.mongodb.core.mapping.MongoId;
60-
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
61-
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
62-
import org.springframework.data.mongodb.core.mapping.TextScore;
63-
import org.springframework.data.mongodb.core.mapping.Unwrapped;
54+
import org.springframework.data.mongodb.core.mapping.*;
6455
import org.springframework.data.mongodb.core.query.BasicQuery;
6556
import org.springframework.data.mongodb.core.query.Criteria;
6657
import org.springframework.data.mongodb.core.query.Query;
@@ -1456,7 +1447,7 @@ void mapStringIdFieldProjection() {
14561447
assertThat(mappedQuery.get("_id"))
14571448
.isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}"));
14581449
}
1459-
1450+
14601451
@Test // GH-3596
14611452
void considersValueConverterWhenPresent() {
14621453

@@ -1509,6 +1500,15 @@ void usesMongoExpressionDocumentAsIsIfItIsNotAnAggregationExpression() {
15091500
assertThat(mappedObject).isEqualTo("{ $expr : { $gt : [ '$field', '$budget'] } }");
15101501
}
15111502

1503+
@Test // GH-4080
1504+
void convertsListOfValuesForPropertyThatHasValueConverterButIsNotCollectionLikeOneByOne() {
1505+
1506+
org.bson.Document mappedObject = mapper.getMappedObject(query(where("text").in("spring", "data")).getQueryObject(),
1507+
context.getPersistentEntity(WithPropertyValueConverter.class));
1508+
1509+
assertThat(mappedObject).isEqualTo("{ 'text' : { $in : ['gnirps', 'atad'] } }");
1510+
}
1511+
15121512
class WithDeepArrayNesting {
15131513

15141514
List<WithNestedArray> level0;
@@ -1787,9 +1787,9 @@ static class Customer {
17871787
static class MyAddress {
17881788
private String street;
17891789
}
1790-
1790+
17911791
static class WithPropertyValueConverter {
1792-
1792+
17931793
@ValueConverter(ReversingValueConverter.class)
17941794
String text;
17951795
}

0 commit comments

Comments
 (0)