Skip to content

Add an option to @Field annotation to control property write rules #3646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -744,9 +744,12 @@ private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, Persist
Object value = accessor.getProperty(prop);

if (value == null) {
if(!prop.isPropertyOmittableOnNull()) {
writeSimpleInternal(value, bson , prop);
}
continue;
}

if (!conversions.isSimpleType(value.getClass())) {
writePropertyInternal(value, dbObjectAccessor, prop);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,18 @@ public boolean isExplicitLanguageProperty() {
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@
@Retention(RetentionPolicy.RUNTIME)
@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()}.
Expand Down Expand Up @@ -65,4 +80,14 @@
* @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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ 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 the {@link DBRef} if the property is a reference.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public boolean isExplicitLanguageProperty() {
public boolean isTextScoreProperty() {
return delegate.isTextScoreProperty();
}

@Override
@Nullable
public DBRef getDBRef() {
Expand Down Expand Up @@ -315,4 +315,9 @@ public Class<?> getAssociationTargetType() {
public <T> PersistentPropertyAccessor<T> getAccessorForOwner(T owner) {
return delegate.getAccessorForOwner(owner);
}

@Override
public boolean isPropertyOmittableOnNull() {
return delegate.isPropertyOmittableOnNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ public void shouldDetectTextScorePropertyCorrectly() {
MongoPersistentProperty property = getPropertyFor(DocumentWithTextScoreProperty.class, "score");
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() {
Expand Down Expand Up @@ -296,6 +303,12 @@ static class DocumentWithImplicitLanguageProperty {
static class DocumentWithTextScoreProperty {
@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 {

Expand Down