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() {