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
This commit is contained in:
committed by
Mark Paluch
parent
7f50fe1cb7
commit
c2f708a37a
@@ -30,6 +30,8 @@ import org.bson.types.ObjectId;
|
|||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.data.annotation.Reference;
|
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.domain.Example;
|
||||||
import org.springframework.data.mapping.Association;
|
import org.springframework.data.mapping.Association;
|
||||||
import org.springframework.data.mapping.MappingException;
|
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.PropertyReferenceException;
|
||||||
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
|
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
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.MongoExpression;
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
|
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
|
||||||
import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext;
|
import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext;
|
||||||
@@ -437,9 +440,22 @@ public class QueryMapper {
|
|||||||
|
|
||||||
if (documentField.getProperty() != null
|
if (documentField.getProperty() != null
|
||||||
&& converter.getCustomConversions().hasValueConverter(documentField.getProperty())) {
|
&& converter.getCustomConversions().hasValueConverter(documentField.getProperty())) {
|
||||||
return converter.getCustomConversions().getPropertyValueConversions()
|
|
||||||
.getValueConverter(documentField.getProperty())
|
MongoConversionContext conversionContext = new MongoConversionContext(new PropertyValueProvider<>() {
|
||||||
.write(value, new MongoConversionContext(null, documentField.getProperty(), converter));
|
@Override
|
||||||
|
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||||
|
throw new IllegalStateException("No enclosing property available");
|
||||||
|
}
|
||||||
|
}, documentField.getProperty(), converter);
|
||||||
|
PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> 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()) {
|
if (documentField.isIdField() && !documentField.isAssociation()) {
|
||||||
|
|||||||
@@ -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.aggregation.TypeBasedAggregationOperationContext;
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
||||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
import org.springframework.data.mongodb.core.mapping.*;
|
||||||
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.query.BasicQuery;
|
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
@@ -1456,7 +1447,7 @@ public class QueryMapperUnitTests {
|
|||||||
assertThat(mappedQuery.get("_id"))
|
assertThat(mappedQuery.get("_id"))
|
||||||
.isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}"));
|
.isEqualTo(org.bson.Document.parse("{ $in: [ {$oid: \"5b8bedceb1e0bfc07b008828\" } ]}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // GH-3596
|
@Test // GH-3596
|
||||||
void considersValueConverterWhenPresent() {
|
void considersValueConverterWhenPresent() {
|
||||||
|
|
||||||
@@ -1509,6 +1500,15 @@ public class QueryMapperUnitTests {
|
|||||||
assertThat(mappedObject).isEqualTo("{ $expr : { $gt : [ '$field', '$budget'] } }");
|
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 {
|
class WithDeepArrayNesting {
|
||||||
|
|
||||||
List<WithNestedArray> level0;
|
List<WithNestedArray> level0;
|
||||||
@@ -1787,9 +1787,9 @@ public class QueryMapperUnitTests {
|
|||||||
static class MyAddress {
|
static class MyAddress {
|
||||||
private String street;
|
private String street;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class WithPropertyValueConverter {
|
static class WithPropertyValueConverter {
|
||||||
|
|
||||||
@ValueConverter(ReversingValueConverter.class)
|
@ValueConverter(ReversingValueConverter.class)
|
||||||
String text;
|
String text;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user