From e3ef84a56c9b3352277579941c3518f78bbc9b73 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 22 Feb 2023 09:42:43 +0100 Subject: [PATCH] Fix regression in findAndReplace when using native MongoDB types as domain value. This commit fixes a regression that prevented native org.bson.Document to serve as source for a findAndReplaceOperation. Closes: #4300 Original Pull Request: #4310 --- .../data/mongodb/core/EntityOperations.java | 4 +++ .../data/mongodb/core/MongoTemplateTests.java | 20 ++++++++++++++ .../mongodb/core/MongoTemplateUnitTests.java | 11 ++++++++ .../core/ReactiveMongoTemplateTests.java | 26 +++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index bb2d2ca5a..db07166b5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -283,6 +283,10 @@ class EntityOperations { * @see EntityProjectionIntrospector#introspect(Class, Class) */ public EntityProjection introspectProjection(Class resultType, Class entityType) { + + if (!queryMapper.getMappingContext().hasPersistentEntityFor(entityType)) { + return (EntityProjection) EntityProjection.nonProjecting(resultType); + } return introspector.introspect(resultType, entityType); } 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 30978bce9..c93c8ade6 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 @@ -2526,6 +2526,26 @@ public class MongoTemplateTests { assertThat(projection.getName()).isEqualTo("Walter"); } + @Test // GH-4300 + public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() { + + MyPerson person = new MyPerson("Walter"); + person.address = new Address("TX", "Austin"); + template.save(person); + + MyPerson previous = template.findAndReplace(query(where("name").is("Walter")), + new org.bson.Document("name", "Heisenberg"), FindAndReplaceOptions.options(), org.bson.Document.class, + "myPerson", MyPerson.class); + + assertThat(previous).isNotNull(); + assertThat(previous.getAddress()).isEqualTo(person.address); + + org.bson.Document loaded = template.execute(MyPerson.class, collection -> { + return collection.find(new org.bson.Document("name", "Heisenberg")).first(); + }); + assertThat(loaded.get("_id")).isEqualTo(new ObjectId(person.id)); + } + @Test // DATAMONGO-407 public void updatesShouldRetainTypeInformationEvenForCollections() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 3f4a63232..6ae652ef8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -2392,6 +2392,17 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { .isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").toString()); } + @Test // GH-4300 + void findAndReplaceAllowsDocumentSourceType() { + + template.findAndReplace(new Query(), new Document("spring", "data"), FindAndReplaceOptions.options().upsert(), + Document.class, "coll-1", Person.class); + + verify(db).getCollection(eq("coll-1"), eq(Document.class)); + verify(collection).findOneAndReplace((Bson) any(Bson.class), eq(new Document("spring", "data")), + any(FindOneAndReplaceOptions.class)); + } + class AutogenerateableId { @Id BigInteger id; 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 6ca3808c9..7740b5a7c 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 @@ -729,6 +729,32 @@ public class ReactiveMongoTemplateTests { }).verifyComplete(); } + @Test // GH-4300 + public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() { + + MongoTemplateTests.MyPerson person = new MongoTemplateTests.MyPerson("Walter"); + person.address = new Address("TX", "Austin"); + template.save(person) // + .as(StepVerifier::create) // + .expectNextCount(1) // + .verifyComplete(); + + template + .findAndReplace(query(where("name").is("Walter")), new org.bson.Document("name", "Heisenberg"), + FindAndReplaceOptions.options(), org.bson.Document.class, "myPerson", MongoTemplateTests.MyPerson.class) + .as(StepVerifier::create) // + .consumeNextWith(actual -> { + assertThat(actual.getAddress()).isEqualTo(person.address); + }).verifyComplete(); + + template.execute(MongoTemplateTests.MyPerson.class, collection -> { + return collection.find(new org.bson.Document("name", "Heisenberg")).first(); + }).as(StepVerifier::create) // + .consumeNextWith(loaded -> { + assertThat(loaded.get("_id")).isEqualTo(new ObjectId(person.id)); + }).verifyComplete(); + } + @Test // DATAMONGO-1827 void findAndReplaceShouldReplaceObjectReturingNew() {