Add an option to @Field annotation to include/exclude null values on write.
Properties can be annotated with `@Field(write=…)` to control whether a property with a null value should be included or omitted (default) during conversion in the target Document. Closes #3407 Original pull request: #3646.
This commit is contained in:
committed by
Mark Paluch
parent
a481636429
commit
b1020d19ba
@@ -744,6 +744,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Object value = accessor.getProperty(prop);
|
||||
|
||||
if (value == null) {
|
||||
if(!prop.isPropertyOmittableOnNull()) {
|
||||
writeSimpleInternal(value, bson , prop);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,4 +285,18 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
public boolean isTextScoreProperty() {
|
||||
return isAnnotationPresent(TextScore.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isPropertyOmittableOnNull()
|
||||
*/
|
||||
public boolean isPropertyOmittableOnNull() {
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(
|
||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
||||
|
||||
if ( annotation != null && annotation.write().equals(Field.Write.ALWAYS) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,21 @@ import org.springframework.core.annotation.AliasFor;
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
public @interface Field {
|
||||
|
||||
/**
|
||||
* Enumeration of write strategies for a field with null value.It decides whether a field with null value has to be
|
||||
* written to the resulting document to be saved to the database.
|
||||
*/
|
||||
enum Write{
|
||||
/*
|
||||
* The field will always be written to the database irrespective of null value.
|
||||
*/
|
||||
ALWAYS,
|
||||
/*
|
||||
* The field will only be written to the database if it has a non null value.
|
||||
*/
|
||||
NON_NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* The key to be used to store the field inside the document. Alias for {@link #name()}.
|
||||
*
|
||||
@@ -65,4 +80,14 @@ public @interface Field {
|
||||
* @since 2.2
|
||||
*/
|
||||
FieldType targetType() default FieldType.IMPLICIT;
|
||||
|
||||
/**
|
||||
* If set to {@link Write#NON_NULL} {@literal null} values will be omitted.
|
||||
* Setting the value to {@link Write#ALWAYS} explicitly adds an entry for the given field
|
||||
* holding {@literal null} as a value {@code 'fieldName' : null }.
|
||||
* <p />
|
||||
* <strong>NOTE</strong> Setting the value to {@link Write#ALWAYS} may lead to increased document size.
|
||||
* @return {@link Write#NON_NULL} by default.
|
||||
*/
|
||||
Write write() default Write.NON_NULL;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,24 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
||||
* @since 1.6
|
||||
*/
|
||||
boolean isTextScoreProperty();
|
||||
|
||||
/**
|
||||
* Returns whether the property is to be written to the document if the value is null <br/>
|
||||
* It's annotated with {@link Field.Write}.
|
||||
*
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
boolean isPropertyOmittableOnNull();
|
||||
|
||||
/**
|
||||
* Returns whether the property is to be written to the document if the value is null <br/>
|
||||
* It's annotated with {@link omitNull}.
|
||||
*
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
boolean isOmitNullProperty();
|
||||
|
||||
/**
|
||||
* Returns the {@link DBRef} if the property is a reference.
|
||||
|
||||
@@ -92,6 +92,11 @@ class UnwrappedMongoPersistentProperty implements MongoPersistentProperty {
|
||||
public boolean isTextScoreProperty() {
|
||||
return delegate.isTextScoreProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOmitNullProperty() {
|
||||
return delegate.isOmitNullProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@@ -315,4 +320,9 @@ class UnwrappedMongoPersistentProperty implements MongoPersistentProperty {
|
||||
public <T> PersistentPropertyAccessor<T> getAccessorForOwner(T owner) {
|
||||
return delegate.getAccessorForOwner(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPropertyOmittableOnNull() {
|
||||
return delegate.isPropertyOmittableOnNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,13 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
assertThat(property.isTextScoreProperty()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2551
|
||||
public void shouldDetectOmittableOnNullPropertyCorrectly() {
|
||||
|
||||
MongoPersistentProperty property = getPropertyFor(DocumentWithOmittableOnNullProperty.class, "write");
|
||||
assertThat(property.isPropertyOmittableOnNull()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-976
|
||||
public void shouldDetectTextScoreAsReadOnlyProperty() {
|
||||
|
||||
@@ -297,6 +304,12 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
@TextScore Float score;
|
||||
}
|
||||
|
||||
static class DocumentWithOmittableOnNullProperty {
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.Field("write") org.springframework.data.mongodb.core.mapping.Field.Write write;
|
||||
|
||||
}
|
||||
|
||||
static class DocumentWithExplicitlyRenamedIdProperty {
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.Field("id") String id;
|
||||
|
||||
Reference in New Issue
Block a user