Skip to content

Commit 8077b18

Browse files
christophstroblmp911de
authored andcommitted
Consider null value settings for types with custom conversion.
This commit fixes an issue where settings regarding storage of null values had been ignored if a custom converter took care of the conversion. Original pull request: #4728 Closes #4710
1 parent 3ec515a commit 8077b18

File tree

3 files changed

+109
-3
lines changed

3 files changed

+109
-3
lines changed

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

+17
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,21 @@ private static Document getOrCreateNestedDocument(String key, Bson source) {
172172

173173
return nested;
174174
}
175+
176+
DocumentAccessor withCheckFieldMapping(boolean checkFieldMapping) {
177+
178+
if(!checkFieldMapping) {
179+
return this;
180+
}
181+
182+
return new DocumentAccessor(this.document) {
183+
@Override
184+
public void put(MongoPersistentProperty prop, @Nullable Object value) {
185+
if(value != null || prop.writeNullValues()) {
186+
super.put(prop, value);
187+
}
188+
}
189+
};
190+
191+
}
175192
}

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,11 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
964964
dbRefObj = proxy.toDBRef();
965965
}
966966

967+
if(obj !=null && conversions.hasCustomWriteTarget(obj.getClass())) {
968+
accessor.withCheckFieldMapping(true).put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get()));
969+
return;
970+
}
971+
967972
dbRefObj = dbRefObj != null ? dbRefObj : createDBRef(obj, prop);
968973

969974
accessor.put(prop, dbRefObj);
@@ -1261,7 +1266,8 @@ private void writeSimpleInternal(@Nullable Object value, Bson bson, String key)
12611266

12621267
private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property,
12631268
PersistentPropertyAccessor<?> persistentPropertyAccessor) {
1264-
DocumentAccessor accessor = new DocumentAccessor(bson);
1269+
1270+
DocumentAccessor accessor = new DocumentAccessor(bson).withCheckFieldMapping(true);
12651271

12661272
if (conversions.hasValueConverter(property)) {
12671273
accessor.put(property, conversions.getPropertyValueConversions().getValueConverter(property).write(value,

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

+85-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.springframework.data.annotation.PersistenceConstructor;
6464
import org.springframework.data.annotation.Transient;
6565
import org.springframework.data.annotation.TypeAlias;
66+
import org.springframework.data.convert.ConverterBuilder;
6667
import org.springframework.data.convert.CustomConversions;
6768
import org.springframework.data.convert.PropertyValueConverter;
6869
import org.springframework.data.convert.PropertyValueConverterFactory;
@@ -2693,9 +2694,85 @@ void shouldWriteNullPropertyCorrectly() {
26932694
converter.write(fieldWrite, document);
26942695

26952696
assertThat(document).containsEntry("writeAlways", null).doesNotContainKey("writeNonNull");
2697+
assertThat(document).containsEntry("writeAlwaysPersonDBRef", null).doesNotContainKey("writeNonNullPersonDBRef");
2698+
}
2699+
2700+
@Test // GH-4710
2701+
void shouldWriteSimplePropertyCorrectlyAfterConversionReturnsNull() {
2702+
2703+
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Integer.class, String.class, it -> null).andReading(it -> null).getConverters().stream().toList());
2704+
2705+
converter = new MappingMongoConverter(resolver, mappingContext);
2706+
converter.setCustomConversions(conversions);
2707+
converter.afterPropertiesSet();
2708+
2709+
WithFieldWrite fieldWrite = new WithFieldWrite();
2710+
fieldWrite.writeAlways = 10;
2711+
fieldWrite.writeNonNull = 20;
2712+
2713+
org.bson.Document document = new org.bson.Document();
2714+
converter.write(fieldWrite, document);
2715+
2716+
assertThat(document).containsEntry("writeAlways", null).doesNotContainKey("writeNonNull");
2717+
}
2718+
2719+
@Test // GH-4710
2720+
void shouldWriteComplexPropertyCorrectlyAfterConversionReturnsNull() {
2721+
2722+
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, String.class, it -> null).andReading(it -> null).getConverters().stream().toList());
2723+
2724+
converter = new MappingMongoConverter(resolver, mappingContext);
2725+
converter.setCustomConversions(conversions);
2726+
converter.afterPropertiesSet();
2727+
2728+
WithFieldWrite fieldWrite = new WithFieldWrite();
2729+
fieldWrite.writeAlwaysPerson = new Person();
2730+
fieldWrite.writeNonNullPerson = new Person();
2731+
2732+
org.bson.Document document = new org.bson.Document();
2733+
converter.write(fieldWrite, document);
2734+
26962735
assertThat(document).containsEntry("writeAlwaysPerson", null).doesNotContainKey("writeNonNullPerson");
26972736
}
26982737

2738+
@Test // GH-4710
2739+
void shouldDelegateWriteOfDBRefToCustomConversionIfConfigured() {
2740+
2741+
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, DBRef.class, it -> new DBRef("persons", "n/a")).andReading(it -> null).getConverters().stream().toList());
2742+
2743+
converter = new MappingMongoConverter(resolver, mappingContext);
2744+
converter.setCustomConversions(conversions);
2745+
converter.afterPropertiesSet();
2746+
2747+
WithFieldWrite fieldWrite = new WithFieldWrite();
2748+
fieldWrite.writeAlwaysPersonDBRef = new Person();
2749+
fieldWrite.writeNonNullPersonDBRef = new Person();
2750+
2751+
org.bson.Document document = new org.bson.Document();
2752+
converter.write(fieldWrite, document);
2753+
2754+
assertThat(document).containsEntry("writeAlwaysPersonDBRef", new DBRef("persons", "n/a"));//.doesNotContainKey("writeNonNullPersonDBRef");
2755+
}
2756+
2757+
@Test // GH-4710
2758+
void shouldDelegateWriteOfDBRefToCustomConversionIfConfiguredAndCheckNulls() {
2759+
2760+
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, DBRef.class, it -> null).andReading(it -> null).getConverters().stream().toList());
2761+
2762+
converter = new MappingMongoConverter(resolver, mappingContext);
2763+
converter.setCustomConversions(conversions);
2764+
converter.afterPropertiesSet();
2765+
2766+
WithFieldWrite fieldWrite = new WithFieldWrite();
2767+
fieldWrite.writeAlwaysPersonDBRef = new Person();
2768+
fieldWrite.writeNonNullPersonDBRef = new Person();
2769+
2770+
org.bson.Document document = new org.bson.Document();
2771+
converter.write(fieldWrite, document);
2772+
2773+
assertThat(document).containsEntry("writeAlwaysPersonDBRef", null).doesNotContainKey("writeNonNullPersonDBRef");
2774+
}
2775+
26992776
@Test // GH-3686
27002777
void readsCollectionContainingNullValue() {
27012778

@@ -4102,13 +4179,19 @@ static class WithFieldWrite {
41024179
@org.springframework.data.mongodb.core.mapping.Field(
41034180
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Integer writeAlways;
41044181

4182+
@org.springframework.data.mongodb.core.mapping.Field(
4183+
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPerson;
4184+
4185+
@org.springframework.data.mongodb.core.mapping.Field(
4186+
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPerson;
4187+
41054188
@org.springframework.data.mongodb.core.mapping.DBRef
41064189
@org.springframework.data.mongodb.core.mapping.Field(
4107-
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPerson;
4190+
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPersonDBRef;
41084191

41094192
@org.springframework.data.mongodb.core.mapping.DBRef
41104193
@org.springframework.data.mongodb.core.mapping.Field(
4111-
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPerson;
4194+
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPersonDBRef;
41124195

41134196
}
41144197

0 commit comments

Comments
 (0)