diff --git a/pom.xml b/pom.xml
index ed0dce4796..e7be0703d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.0.0-SNAPSHOT
+ 4.0.x-GH-4184-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index c28a240d2c..3f0cd51c59 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.0.0-SNAPSHOT
+ 4.0.x-GH-4184-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 0412911f82..877f2282bf 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.0.0-SNAPSHOT
+ 4.0.x-GH-4184-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 1f8c5b28a8..bf2d74cb65 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.0.0-SNAPSHOT
+ 4.0.x-GH-4184-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java
index 1a79028196..80558b97ee 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java
@@ -1326,9 +1326,10 @@ default long exactCount(Query query, String collectionName) {
/**
* Insert the object into the collection for the entity type of the object to save.
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
- * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
- * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
- * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
+ * If your object has an {@literal Id} property which holds a {@literal null} value, it will be set with the generated
+ * Id from MongoDB. If your Id property is a String then MongoDB ObjectId will be used to populate that string.
+ * Otherwise, the conversion from ObjectId to your property type will be handled by Spring's BeanWrapper class that
+ * leverages Type Conversion API. See
* Spring's
* Type Conversion" for more details.
* Insert is used to initially store the object into the database. To update an existing object use the save method.
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
index fc712461a7..5a799bcbdf 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
@@ -272,7 +272,7 @@ MappedDocument prepareId(Class type) {
*/
MappedDocument prepareId(@Nullable MongoPersistentEntity entity) {
- if (entity == null) {
+ if (entity == null || source.hasId()) {
return source;
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java
index 24202ba1a7..698910785c 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java
@@ -1093,9 +1093,10 @@ default Mono exactCount(Query query, String collectionName) {
/**
* Insert the object into the collection for the entity type of the object to save.
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
- * If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
- * String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
- * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
+ * If your object has an {@literal Id} property which holds a {@literal null} value, it will be set with the generated
+ * Id from MongoDB. If your Id property is a String then MongoDB ObjectId will be used to populate that string.
+ * Otherwise, the conversion from ObjectId to your property type will be handled by Spring's BeanWrapper class that
+ * leverages Type Conversion API. See
* Spring's
* Type Conversion" for more details.
* Insert is used to initially store the object into the database. To update an existing object use the save method.
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
index e07149c7c3..7a4d78a215 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
@@ -3636,6 +3636,26 @@ public void saveAndLoadStringThatIsAnObjectIdAsString() {
assertThat(target).isEqualTo(source);
}
+ @Test // GH-4184
+ void insertHonorsExistingRawId() {
+
+ RawStringId source = new RawStringId();
+ source.id = "abc";
+ source.value = "new value";
+
+ template.insert(source);
+
+ org.bson.Document result = template
+ .execute(db -> db.getCollection(template.getCollectionName(RawStringId.class))
+ .find().limit(1).cursor().next());
+
+ assertThat(result).isNotNull();
+ assertThat(result.get("_id")).isEqualTo("abc");
+
+ RawStringId target = template.findOne(query(where("id").is(source.id)), RawStringId.class);
+ assertThat(target).isEqualTo(source);
+ }
+
@Test // GH-4026
void saveShouldGenerateNewIdOfTypeIfExplicitlyDefined() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryOperationsUnitTests.java
index 0a01bed2b4..2d412bab83 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryOperationsUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryOperationsUnitTests.java
@@ -205,6 +205,15 @@ void insertContextDoesNotAddConvertedIdForMongoIdTypesTargetingObjectId() {
});
}
+ @Test // GH-4184
+ void insertContextDoesNotOverrideExistingId() {
+
+ assertThat(queryOperations.createInsertContext(new Document("_id", "abc")).prepareId(Person.class).getDocument())//
+ .satisfies(result -> {
+ assertThat(result).isEqualTo(new Document("_id", "abc"));
+ });
+ }
+
static class Person {
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java
index 0dfe01a5db..1a4e684e25 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java
@@ -218,6 +218,23 @@ void insertShouldGenerateNewIdOfTypeIfExplicitlyDefined() {
}).verifyComplete();
}
+ @Test // GH-4184
+ void insertHonorsExistingRawId() {
+
+ MongoTemplateTests.RawStringId source = new MongoTemplateTests.RawStringId();
+ source.id = "abc";
+ source.value = "new value";
+
+ template.insert(source)
+ .then(template.execute(db -> Flux.from(
+ db.getCollection(template.getCollectionName(MongoTemplateTests.RawStringId.class)).find().limit(1).first()))
+ .next())
+ .as(StepVerifier::create).consumeNextWith(result -> {
+ assertThat(result).isNotNull();
+ assertThat(result.get("_id")).isEqualTo("abc");
+ });
+ }
+
@Test // DATAMONGO-1444
void insertsSimpleEntityCorrectly() {