|
49 | 49 | import org.springframework.core.convert.support.DefaultConversionService;
|
50 | 50 | import org.springframework.data.annotation.Reference;
|
51 | 51 | import org.springframework.data.convert.CustomConversions;
|
| 52 | +import org.springframework.data.convert.PropertyValueConverter; |
52 | 53 | import org.springframework.data.convert.TypeMapper;
|
| 54 | +import org.springframework.data.convert.ValueConversionContext; |
53 | 55 | import org.springframework.data.mapping.Association;
|
54 | 56 | import org.springframework.data.mapping.InstanceCreatorMetadata;
|
55 | 57 | import org.springframework.data.mapping.MappingException;
|
@@ -164,12 +166,11 @@ public MappingMongoConverter(DbRefResolver dbRefResolver,
|
164 | 166 | this.idMapper = new QueryMapper(this);
|
165 | 167 |
|
166 | 168 | this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
|
167 |
| - this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, |
168 |
| - (prop, bson, evaluator, path) -> { |
| 169 | + this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, (prop, bson, evaluator, path) -> { |
169 | 170 |
|
170 |
| - ConversionContext context = getConversionContext(path); |
171 |
| - return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); |
172 |
| - }); |
| 171 | + ConversionContext context = getConversionContext(path); |
| 172 | + return MappingMongoConverter.this.getValueInternal(context, prop, bson, evaluator); |
| 173 | + }); |
173 | 174 |
|
174 | 175 | this.referenceLookupDelegate = new ReferenceLookupDelegate(mappingContext, spELContext);
|
175 | 176 | this.documentPointerFactory = new DocumentPointerFactory(conversionService, mappingContext);
|
@@ -880,7 +881,10 @@ private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, Persist
|
880 | 881 | Object value = accessor.getProperty(prop);
|
881 | 882 |
|
882 | 883 | if (value == null) {
|
883 |
| - if (prop.writeNullValues()) { |
| 884 | + |
| 885 | + if (conversions.hasValueConverter(prop)) { |
| 886 | + dbObjectAccessor.put(prop, applyPropertyConversion(null, prop, accessor)); |
| 887 | + } else { |
884 | 888 | dbObjectAccessor.put(prop, null);
|
885 | 889 | }
|
886 | 890 | } else if (!conversions.isSimpleType(value.getClass())) {
|
@@ -918,14 +922,7 @@ protected void writePropertyInternal(@Nullable Object obj, DocumentAccessor acce
|
918 | 922 | TypeInformation<?> type = prop.getTypeInformation();
|
919 | 923 |
|
920 | 924 | if (conversions.hasValueConverter(prop)) {
|
921 |
| - accessor.put(prop, conversions.getPropertyValueConversions().getValueConverter(prop).write(obj, |
922 |
| - new MongoConversionContext(new PropertyValueProvider<>() { |
923 |
| - @Nullable |
924 |
| - @Override |
925 |
| - public <T> T getPropertyValue(MongoPersistentProperty property) { |
926 |
| - return (T) persistentPropertyAccessor.getProperty(property); |
927 |
| - } |
928 |
| - }, prop, this, spELContext))); |
| 925 | + accessor.put(prop, applyPropertyConversion(obj, prop, persistentPropertyAccessor)); |
929 | 926 | return;
|
930 | 927 | }
|
931 | 928 |
|
@@ -964,8 +961,8 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
|
964 | 961 | dbRefObj = proxy.toDBRef();
|
965 | 962 | }
|
966 | 963 |
|
967 |
| - if(obj !=null && conversions.hasCustomWriteTarget(obj.getClass())) { |
968 |
| - accessor.withCheckFieldMapping(true).put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get())); |
| 964 | + if (obj != null && conversions.hasCustomWriteTarget(obj.getClass())) { |
| 965 | + accessor.put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get())); |
969 | 966 | return;
|
970 | 967 | }
|
971 | 968 |
|
@@ -1267,24 +1264,34 @@ private void writeSimpleInternal(@Nullable Object value, Bson bson, String key)
|
1267 | 1264 | private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property,
|
1268 | 1265 | PersistentPropertyAccessor<?> persistentPropertyAccessor) {
|
1269 | 1266 |
|
1270 |
| - DocumentAccessor accessor = new DocumentAccessor(bson).withCheckFieldMapping(true); |
| 1267 | + DocumentAccessor accessor = new DocumentAccessor(bson); |
1271 | 1268 |
|
1272 | 1269 | if (conversions.hasValueConverter(property)) {
|
1273 |
| - accessor.put(property, conversions.getPropertyValueConversions().getValueConverter(property).write(value, |
1274 |
| - new MongoConversionContext(new PropertyValueProvider<>() { |
1275 |
| - @Nullable |
1276 |
| - @Override |
1277 |
| - public <T> T getPropertyValue(MongoPersistentProperty property) { |
1278 |
| - return (T) persistentPropertyAccessor.getProperty(property); |
1279 |
| - } |
1280 |
| - }, property, this, spELContext))); |
| 1270 | + accessor.put(property, applyPropertyConversion(value, property, persistentPropertyAccessor)); |
1281 | 1271 | return;
|
1282 | 1272 | }
|
1283 | 1273 |
|
1284 | 1274 | accessor.put(property, getPotentiallyConvertedSimpleWrite(value,
|
1285 | 1275 | property.hasExplicitWriteTarget() ? property.getFieldType() : Object.class));
|
1286 | 1276 | }
|
1287 | 1277 |
|
| 1278 | + @Nullable |
| 1279 | + @SuppressWarnings("unchecked") |
| 1280 | + private Object applyPropertyConversion(@Nullable Object value, MongoPersistentProperty property, |
| 1281 | + PersistentPropertyAccessor<?> persistentPropertyAccessor) { |
| 1282 | + MongoConversionContext context = new MongoConversionContext(new PropertyValueProvider<>() { |
| 1283 | + |
| 1284 | + @Nullable |
| 1285 | + @Override |
| 1286 | + public <T> T getPropertyValue(MongoPersistentProperty property) { |
| 1287 | + return (T) persistentPropertyAccessor.getProperty(property); |
| 1288 | + } |
| 1289 | + }, property, this, spELContext); |
| 1290 | + PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter = conversions |
| 1291 | + .getPropertyValueConversions().getValueConverter(property); |
| 1292 | + return value != null ? valueConverter.write(value, context) : valueConverter.writeNull(context); |
| 1293 | + } |
| 1294 | + |
1288 | 1295 | /**
|
1289 | 1296 | * Checks whether we have a custom conversion registered for the given value into an arbitrary simple Mongo type.
|
1290 | 1297 | * Returns the converted value if so. If not, we perform special enum handling or simply return the value as is.
|
@@ -1925,14 +1932,18 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
|
1925 | 1932 | String expression = property.getSpelExpression();
|
1926 | 1933 | Object value = expression != null ? evaluator.evaluate(expression) : accessor.get(property);
|
1927 | 1934 |
|
1928 |
| - if (value == null) { |
1929 |
| - return null; |
1930 |
| - } |
1931 |
| - |
1932 | 1935 | CustomConversions conversions = context.getCustomConversions();
|
1933 | 1936 | if (conversions.hasValueConverter(property)) {
|
1934 |
| - return (T) conversions.getPropertyValueConversions().getValueConverter(property).read(value, |
1935 |
| - new MongoConversionContext(this, property, context.getSourceConverter(), spELContext)); |
| 1937 | + MongoConversionContext conversionContext = new MongoConversionContext(this, property, |
| 1938 | + context.getSourceConverter(), spELContext); |
| 1939 | + PropertyValueConverter<Object, Object, ValueConversionContext<MongoPersistentProperty>> valueConverter = conversions |
| 1940 | + .getPropertyValueConversions().getValueConverter(property); |
| 1941 | + return (T) (value != null ? valueConverter.read(value, conversionContext) |
| 1942 | + : valueConverter.readNull(conversionContext)); |
| 1943 | + } |
| 1944 | + |
| 1945 | + if (value == null) { |
| 1946 | + return null; |
1936 | 1947 | }
|
1937 | 1948 |
|
1938 | 1949 | ConversionContext contextToUse = context.forProperty(property);
|
|
0 commit comments