Skip to content

Commit 791f8b2

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 fe25694 commit 791f8b2

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
@@ -987,6 +987,11 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
987987
dbRefObj = proxy.toDBRef();
988988
}
989989

990+
if(obj !=null && conversions.hasCustomWriteTarget(obj.getClass())) {
991+
accessor.withCheckFieldMapping(true).put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get()));
992+
return;
993+
}
994+
990995
dbRefObj = dbRefObj != null ? dbRefObj : createDBRef(obj, prop);
991996

992997
accessor.put(prop, dbRefObj);
@@ -1284,7 +1289,8 @@ private void writeSimpleInternal(@Nullable Object value, Bson bson, String key)
12841289

12851290
private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property,
12861291
PersistentPropertyAccessor<?> persistentPropertyAccessor) {
1287-
DocumentAccessor accessor = new DocumentAccessor(bson);
1292+
1293+
DocumentAccessor accessor = new DocumentAccessor(bson).withCheckFieldMapping(true);
12881294

12891295
if (conversions.hasValueConverter(property)) {
12901296
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)