diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java index 2b785ff52..00d148b89 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicUpdate.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collections; import org.bson.Document; +import org.springframework.lang.Nullable; /** * @author Thomas Risberg @@ -42,7 +43,7 @@ public class BasicUpdate extends Update { } @Override - public Update set(String key, Object value) { + public Update set(String key, @Nullable Object value) { updateObject.put("$set", Collections.singletonMap(key, value)); return this; } @@ -60,7 +61,7 @@ public class BasicUpdate extends Update { } @Override - public Update push(String key, Object value) { + public Update push(String key, @Nullable Object value) { updateObject.put("$push", Collections.singletonMap(key, value)); return this; } @@ -74,7 +75,7 @@ public class BasicUpdate extends Update { } @Override - public Update addToSet(String key, Object value) { + public Update addToSet(String key, @Nullable Object value) { updateObject.put("$addToSet", Collections.singletonMap(key, value)); return this; } @@ -86,7 +87,7 @@ public class BasicUpdate extends Update { } @Override - public Update pull(String key, Object value) { + public Update pull(String key, @Nullable Object value) { updateObject.put("$pull", Collections.singletonMap(key, value)); return this; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java index 4957bb5d5..edb79588d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java @@ -27,7 +27,6 @@ import java.util.Objects; import java.util.Set; import org.bson.Document; - import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -68,7 +67,7 @@ public class Update implements UpdateDefinition { * @param key * @return */ - public static Update update(String key, Object value) { + public static Update update(String key, @Nullable Object value) { return new Update().set(key, value); } @@ -110,11 +109,12 @@ public class Update implements UpdateDefinition { * Update using the {@literal $set} update modifier * * @param key - * @param value - * @return + * @param value can be {@literal null}. In this case the property remains in the db with a {@literal null} value. To + * remove it use {@link #unset(String)}. + * @return this. * @see MongoDB Update operator: $set */ - public Update set(String key, Object value) { + public Update set(String key, @Nullable Object value) { addMultiFieldOperation("$set", key, value); return this; } @@ -123,12 +123,12 @@ public class Update implements UpdateDefinition { * Update using the {@literal $setOnInsert} update modifier * * @param key - * @param value + * @param value can be {@literal null}. * @return * @see MongoDB Update operator: * $setOnInsert */ - public Update setOnInsert(String key, Object value) { + public Update setOnInsert(String key, @Nullable Object value) { addMultiFieldOperation("$setOnInsert", key, value); return this; } @@ -175,7 +175,7 @@ public class Update implements UpdateDefinition { * @return * @see MongoDB Update operator: $push */ - public Update push(String key, Object value) { + public Update push(String key, @Nullable Object value) { addMultiFieldOperation("$push", key, value); return this; } @@ -238,7 +238,7 @@ public class Update implements UpdateDefinition { * @see MongoDB Update operator: * $addToSet */ - public Update addToSet(String key, Object value) { + public Update addToSet(String key, @Nullable Object value) { addMultiFieldOperation("$addToSet", key, value); return this; } @@ -264,7 +264,7 @@ public class Update implements UpdateDefinition { * @return * @see MongoDB Update operator: $pull */ - public Update pull(String key, Object value) { + public Update pull(String key, @Nullable Object value) { addMultiFieldOperation("$pull", key, value); return this; } @@ -472,7 +472,7 @@ public class Update implements UpdateDefinition { this.keysToUpdate.add(key); } - protected void addMultiFieldOperation(String operator, String key, Object value) { + protected void addMultiFieldOperation(String operator, String key, @Nullable Object value) { Assert.hasText(key, "Key/Path for update must not be null or blank."); Object existingValue = this.modifierOps.get(operator); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index 2f46f87d6..a90371de5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -36,6 +36,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -272,6 +273,22 @@ public class MongoTemplateUpdateTests { } + @Test // DATAMMONGO-2423 + void nullValueShouldBePropagatedToDatabase() { + + Book currentRead = new Book(); + currentRead.id = 1; + currentRead.author = new Author("Brent", "Weeks"); + currentRead.title = "The Burning White"; + + template.save(currentRead); + + template.update(Book.class).apply(new Update().set("title", null)).first(); + + assertThat(collection(Book.class).find(new org.bson.Document("_id", currentRead.id)).first()).containsEntry("title", + null); + } + private List all(Class type) { return collection(type).find(new org.bson.Document()).into(new ArrayList<>()); }