|
53 | 53 | import org.springframework.core.env.StandardEnvironment; |
54 | 54 | import org.springframework.data.annotation.Reference; |
55 | 55 | import org.springframework.data.convert.CustomConversions; |
| 56 | +import org.springframework.data.convert.PropertyValueConverter; |
56 | 57 | import org.springframework.data.convert.TypeMapper; |
| 58 | +import org.springframework.data.convert.ValueConversionContext; |
57 | 59 | import org.springframework.data.mapping.Association; |
58 | 60 | import org.springframework.data.mapping.InstanceCreatorMetadata; |
59 | 61 | import org.springframework.data.mapping.MappingException; |
@@ -176,12 +178,11 @@ public MappingMongoConverter(DbRefResolver dbRefResolver, |
176 | 178 | this.idMapper = new QueryMapper(this); |
177 | 179 |
|
178 | 180 | this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE); |
179 | | - this.dbRefProxyHandler = new DefaultDbRefProxyHandler(mappingContext, |
180 | | - (prop, bson, evaluator, path) -> { |
| 181 | + this.dbRefProxyHandler = new DefaultDbRefProxyHandler(mappingContext, (prop, bson, evaluator, path) -> { |
181 | 182 |
|
182 | | - ConversionContext context = getConversionContext(path); |
183 | | - return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); |
184 | | - }, expressionEvaluatorFactory::create); |
| 183 | + ConversionContext context = getConversionContext(path); |
| 184 | + return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); |
| 185 | + }, expressionEvaluatorFactory::create); |
185 | 186 |
|
186 | 187 | this.referenceLookupDelegate = new ReferenceLookupDelegate(mappingContext, spELContext); |
187 | 188 | this.documentPointerFactory = new DocumentPointerFactory(conversionService, mappingContext); |
@@ -903,7 +904,10 @@ private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, Persist |
903 | 904 | Object value = accessor.getProperty(prop); |
904 | 905 |
|
905 | 906 | if (value == null) { |
906 | | - if (prop.writeNullValues()) { |
| 907 | + |
| 908 | + if (conversions.hasValueConverter(prop)) { |
| 909 | + dbObjectAccessor.put(prop, applyPropertyConversion(null, prop, accessor)); |
| 910 | + } else { |
907 | 911 | dbObjectAccessor.put(prop, null); |
908 | 912 | } |
909 | 913 | } else if (!conversions.isSimpleType(value.getClass())) { |
@@ -941,14 +945,7 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce |
941 | 945 | TypeInformation<?> type = prop.getTypeInformation(); |
942 | 946 |
|
943 | 947 | if (conversions.hasValueConverter(prop)) { |
944 | | - accessor.put(prop, conversions.getPropertyValueConversions().getValueConverter(prop).write(obj, |
945 | | - new MongoConversionContext(new PropertyValueProvider<>() { |
946 | | - @Nullable |
947 | | - @Override |
948 | | - public <T> T getPropertyValue(MongoPersistentProperty property) { |
949 | | - return (T) persistentPropertyAccessor.getProperty(property); |
950 | | - } |
951 | | - }, prop, this, spELContext))); |
| 948 | + accessor.put(prop, applyPropertyConversion(obj, prop, persistentPropertyAccessor)); |
952 | 949 | return; |
953 | 950 | } |
954 | 951 |
|
@@ -987,8 +984,8 @@ public <T> T getPropertyValue(MongoPersistentProperty property) { |
987 | 984 | dbRefObj = proxy.toDBRef(); |
988 | 985 | } |
989 | 986 |
|
990 | | - if(obj !=null && conversions.hasCustomWriteTarget(obj.getClass())) { |
991 | | - accessor.withCheckFieldMapping(true).put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get())); |
| 987 | + if (obj != null && conversions.hasCustomWriteTarget(obj.getClass())) { |
| 988 | + accessor.put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get())); |
992 | 989 | return; |
993 | 990 | } |
994 | 991 |
|
@@ -1290,24 +1287,34 @@ private void writeSimpleInternal(@Nullable Object value, Bson bson, String key) |
1290 | 1287 | private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property, |
1291 | 1288 | PersistentPropertyAccessor<?> persistentPropertyAccessor) { |
1292 | 1289 |
|
1293 | | - DocumentAccessor accessor = new DocumentAccessor(bson).withCheckFieldMapping(true); |
| 1290 | + DocumentAccessor accessor = new DocumentAccessor(bson); |
1294 | 1291 |
|
1295 | 1292 | if (conversions.hasValueConverter(property)) { |
1296 | | - accessor.put(property, conversions.getPropertyValueConversions().getValueConverter(property).write(value, |
1297 | | - new MongoConversionContext(new PropertyValueProvider<>() { |
1298 | | - @Nullable |
1299 | | - @Override |
1300 | | - public <T> T getPropertyValue(MongoPersistentProperty property) { |
1301 | | - return (T) persistentPropertyAccessor.getProperty(property); |
1302 | | - } |
1303 | | - }, property, this, spELContext))); |
| 1293 | + accessor.put(property, applyPropertyConversion(value, property, persistentPropertyAccessor)); |
1304 | 1294 | return; |
1305 | 1295 | } |
1306 | 1296 |
|
1307 | 1297 | accessor.put(property, getPotentiallyConvertedSimpleWrite(value, |
1308 | 1298 | property.hasExplicitWriteTarget() ? property.getFieldType() : Object.class)); |
1309 | 1299 | } |
1310 | 1300 |
|
| 1301 | + @Nullable |
| 1302 | + @SuppressWarnings("unchecked") |
| 1303 | + private Object applyPropertyConversion(@Nullable Object value, MongoPersistentProperty property, |
| 1304 | + PersistentPropertyAccessor<?> persistentPropertyAccessor) { |
| 1305 | + MongoConversionContext context = new MongoConversionContext(new PropertyValueProvider<>() { |
| 1306 | + |
| 1307 | + @Nullable |
| 1308 | + @Override |
| 1309 | + public <T> T getPropertyValue(MongoPersistentProperty property) { |
| 1310 | + return (T) persistentPropertyAccessor.getProperty(property); |
| 1311 | + } |
| 1312 | + }, property, this, spELContext); |
| 1313 | + PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter = conversions |
| 1314 | + .getPropertyValueConversions().getValueConverter(property); |
| 1315 | + return value != null ? valueConverter.write(value, context) : valueConverter.writeNull(context); |
| 1316 | + } |
| 1317 | + |
1311 | 1318 | /** |
1312 | 1319 | * Checks whether we have a custom conversion registered for the given value into an arbitrary simple Mongo type. |
1313 | 1320 | * Returns the converted value if so. If not, we perform special enum handling or simply return the value as is. |
@@ -1948,14 +1955,18 @@ public <T> T getPropertyValue(MongoPersistentProperty property) { |
1948 | 1955 | String expression = property.getSpelExpression(); |
1949 | 1956 | Object value = expression != null ? evaluator.evaluate(expression) : accessor.get(property); |
1950 | 1957 |
|
1951 | | - if (value == null) { |
1952 | | - return null; |
1953 | | - } |
1954 | | - |
1955 | 1958 | CustomConversions conversions = context.getCustomConversions(); |
1956 | 1959 | if (conversions.hasValueConverter(property)) { |
1957 | | - return (T) conversions.getPropertyValueConversions().getValueConverter(property).read(value, |
1958 | | - new MongoConversionContext(this, property, context.getSourceConverter(), spELContext)); |
| 1960 | + MongoConversionContext conversionContext = new MongoConversionContext(this, property, |
| 1961 | + context.getSourceConverter(), spELContext); |
| 1962 | + PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter = conversions |
| 1963 | + .getPropertyValueConversions().getValueConverter(property); |
| 1964 | + return (T) (value != null ? valueConverter.read(value, conversionContext) |
| 1965 | + : valueConverter.readNull(conversionContext)); |
| 1966 | + } |
| 1967 | + |
| 1968 | + if (value == null) { |
| 1969 | + return null; |
1959 | 1970 | } |
1960 | 1971 |
|
1961 | 1972 | ConversionContext contextToUse = context.forProperty(property); |
|
0 commit comments