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 90fb40fb9..41bbf10ef 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 @@ -30,6 +30,8 @@ import org.bson.types.ObjectId; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Reference; +import org.springframework.data.convert.PropertyValueConverter; +import org.springframework.data.convert.ValueConversionContext; import org.springframework.data.domain.Example; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.MappingException; @@ -40,6 +42,7 @@ import org.springframework.data.mapping.PropertyPath; import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.data.mapping.context.InvalidPersistentPropertyPath; import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.PropertyValueProvider; import org.springframework.data.mongodb.MongoExpression; import org.springframework.data.mongodb.core.aggregation.AggregationExpression; import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext; @@ -437,9 +440,22 @@ public class QueryMapper { if (documentField.getProperty() != null && converter.getCustomConversions().hasValueConverter(documentField.getProperty())) { - return converter.getCustomConversions().getPropertyValueConversions() - .getValueConverter(documentField.getProperty()) - .write(value, new MongoConversionContext(null, documentField.getProperty(), converter)); + + MongoConversionContext conversionContext = new MongoConversionContext(new PropertyValueProvider<>() { + @Override + public T getPropertyValue(MongoPersistentProperty property) { + throw new IllegalStateException("No enclosing property available"); + } + }, documentField.getProperty(), converter); + PropertyValueConverter> valueConverter = converter + .getCustomConversions().getPropertyValueConversions().getValueConverter(documentField.getProperty()); + + /* might be an $in clause with multiple entries */ + if (!documentField.getProperty().isCollectionLike() && sourceValue instanceof Collection collection) { + return collection.stream().map(it -> valueConverter.write(it, conversionContext)).collect(Collectors.toList()); + } + + return valueConverter.write(value, conversionContext); } if (documentField.isIdField() && !documentField.isAssociation()) { 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 68a77ad14..fc0345b3d 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 @@ -51,16 +51,7 @@ import org.springframework.data.mongodb.core.aggregation.EvaluationOperators.Exp import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.geo.GeoJsonPolygon; -import org.springframework.data.mongodb.core.mapping.DBRef; -import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.data.mongodb.core.mapping.DocumentReference; -import org.springframework.data.mongodb.core.mapping.Field; -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.MongoPersistentEntity; -import org.springframework.data.mongodb.core.mapping.TextScore; -import org.springframework.data.mongodb.core.mapping.Unwrapped; +import org.springframework.data.mongodb.core.mapping.*; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; @@ -1456,7 +1447,7 @@ public class QueryMapperUnitTests { assertThat(mappedQuery.get("_id")) .isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}")); } - + @Test // GH-3596 void considersValueConverterWhenPresent() { @@ -1509,6 +1500,15 @@ public class QueryMapperUnitTests { assertThat(mappedObject).isEqualTo("{ $expr : { $gt : [ '$field', '$budget'] } }"); } + @Test // GH-4080 + void convertsListOfValuesForPropertyThatHasValueConverterButIsNotCollectionLikeOneByOne() { + + org.bson.Document mappedObject = mapper.getMappedObject(query(where("text").in("spring", "data")).getQueryObject(), + context.getPersistentEntity(WithPropertyValueConverter.class)); + + assertThat(mappedObject).isEqualTo("{ 'text' : { $in : ['gnirps', 'atad'] } }"); + } + class WithDeepArrayNesting { List level0; @@ -1787,9 +1787,9 @@ public class QueryMapperUnitTests { static class MyAddress { private String street; } - + static class WithPropertyValueConverter { - + @ValueConverter(ReversingValueConverter.class) String text; }