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
This commit is contained in:
committed by
Mark Paluch
parent
28ec15b4e7
commit
2e503cd22b
@@ -172,4 +172,21 @@ class DocumentAccessor {
|
||||
|
||||
return nested;
|
||||
}
|
||||
|
||||
DocumentAccessor withCheckFieldMapping(boolean checkFieldMapping) {
|
||||
|
||||
if(!checkFieldMapping) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new DocumentAccessor(this.document) {
|
||||
@Override
|
||||
public void put(MongoPersistentProperty prop, @Nullable Object value) {
|
||||
if(value != null || prop.writeNullValues()) {
|
||||
super.put(prop, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,6 +987,11 @@ public class MappingMongoConverter extends AbstractMongoConverter
|
||||
dbRefObj = proxy.toDBRef();
|
||||
}
|
||||
|
||||
if(obj !=null && conversions.hasCustomWriteTarget(obj.getClass())) {
|
||||
accessor.withCheckFieldMapping(true).put(prop, doConvert(obj, conversions.getCustomWriteTarget(obj.getClass()).get()));
|
||||
return;
|
||||
}
|
||||
|
||||
dbRefObj = dbRefObj != null ? dbRefObj : createDBRef(obj, prop);
|
||||
|
||||
accessor.put(prop, dbRefObj);
|
||||
@@ -1284,7 +1289,8 @@ public class MappingMongoConverter extends AbstractMongoConverter
|
||||
|
||||
private void writeSimpleInternal(@Nullable Object value, Bson bson, MongoPersistentProperty property,
|
||||
PersistentPropertyAccessor<?> persistentPropertyAccessor) {
|
||||
DocumentAccessor accessor = new DocumentAccessor(bson);
|
||||
|
||||
DocumentAccessor accessor = new DocumentAccessor(bson).withCheckFieldMapping(true);
|
||||
|
||||
if (conversions.hasValueConverter(property)) {
|
||||
accessor.put(property, conversions.getPropertyValueConversions().getValueConverter(property).write(value,
|
||||
|
||||
@@ -63,6 +63,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.convert.ConverterBuilder;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.convert.PropertyValueConverter;
|
||||
import org.springframework.data.convert.PropertyValueConverterFactory;
|
||||
@@ -2693,9 +2694,85 @@ class MappingMongoConverterUnitTests {
|
||||
converter.write(fieldWrite, document);
|
||||
|
||||
assertThat(document).containsEntry("writeAlways", null).doesNotContainKey("writeNonNull");
|
||||
assertThat(document).containsEntry("writeAlwaysPersonDBRef", null).doesNotContainKey("writeNonNullPersonDBRef");
|
||||
}
|
||||
|
||||
@Test // GH-4710
|
||||
void shouldWriteSimplePropertyCorrectlyAfterConversionReturnsNull() {
|
||||
|
||||
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Integer.class, String.class, it -> null).andReading(it -> null).getConverters().stream().toList());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(conversions);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
WithFieldWrite fieldWrite = new WithFieldWrite();
|
||||
fieldWrite.writeAlways = 10;
|
||||
fieldWrite.writeNonNull = 20;
|
||||
|
||||
org.bson.Document document = new org.bson.Document();
|
||||
converter.write(fieldWrite, document);
|
||||
|
||||
assertThat(document).containsEntry("writeAlways", null).doesNotContainKey("writeNonNull");
|
||||
}
|
||||
|
||||
@Test // GH-4710
|
||||
void shouldWriteComplexPropertyCorrectlyAfterConversionReturnsNull() {
|
||||
|
||||
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, String.class, it -> null).andReading(it -> null).getConverters().stream().toList());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(conversions);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
WithFieldWrite fieldWrite = new WithFieldWrite();
|
||||
fieldWrite.writeAlwaysPerson = new Person();
|
||||
fieldWrite.writeNonNullPerson = new Person();
|
||||
|
||||
org.bson.Document document = new org.bson.Document();
|
||||
converter.write(fieldWrite, document);
|
||||
|
||||
assertThat(document).containsEntry("writeAlwaysPerson", null).doesNotContainKey("writeNonNullPerson");
|
||||
}
|
||||
|
||||
@Test // GH-4710
|
||||
void shouldDelegateWriteOfDBRefToCustomConversionIfConfigured() {
|
||||
|
||||
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, DBRef.class, it -> new DBRef("persons", "n/a")).andReading(it -> null).getConverters().stream().toList());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(conversions);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
WithFieldWrite fieldWrite = new WithFieldWrite();
|
||||
fieldWrite.writeAlwaysPersonDBRef = new Person();
|
||||
fieldWrite.writeNonNullPersonDBRef = new Person();
|
||||
|
||||
org.bson.Document document = new org.bson.Document();
|
||||
converter.write(fieldWrite, document);
|
||||
|
||||
assertThat(document).containsEntry("writeAlwaysPersonDBRef", new DBRef("persons", "n/a"));//.doesNotContainKey("writeNonNullPersonDBRef");
|
||||
}
|
||||
|
||||
@Test // GH-4710
|
||||
void shouldDelegateWriteOfDBRefToCustomConversionIfConfiguredAndCheckNulls() {
|
||||
|
||||
MongoCustomConversions conversions = new MongoCustomConversions(ConverterBuilder.writing(Person.class, DBRef.class, it -> null).andReading(it -> null).getConverters().stream().toList());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(conversions);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
WithFieldWrite fieldWrite = new WithFieldWrite();
|
||||
fieldWrite.writeAlwaysPersonDBRef = new Person();
|
||||
fieldWrite.writeNonNullPersonDBRef = new Person();
|
||||
|
||||
org.bson.Document document = new org.bson.Document();
|
||||
converter.write(fieldWrite, document);
|
||||
|
||||
assertThat(document).containsEntry("writeAlwaysPersonDBRef", null).doesNotContainKey("writeNonNullPersonDBRef");
|
||||
}
|
||||
|
||||
@Test // GH-3686
|
||||
void readsCollectionContainingNullValue() {
|
||||
|
||||
@@ -4102,13 +4179,19 @@ class MappingMongoConverterUnitTests {
|
||||
@org.springframework.data.mongodb.core.mapping.Field(
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Integer writeAlways;
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef
|
||||
@org.springframework.data.mongodb.core.mapping.Field(
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPerson;
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPerson;
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.Field(
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPerson;
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef
|
||||
@org.springframework.data.mongodb.core.mapping.Field(
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPerson;
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.NON_NULL) Person writeNonNullPersonDBRef;
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef
|
||||
@org.springframework.data.mongodb.core.mapping.Field(
|
||||
write = org.springframework.data.mongodb.core.mapping.Field.Write.ALWAYS) Person writeAlwaysPersonDBRef;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user