From 70a237032afc04a8cd02e36ff80501f45a7b0d0e Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 10 Nov 2020 16:34:44 +0100 Subject: [PATCH 1/5] DATAMONGO-2652 - Prepare branch --- pom.xml | 4 ++-- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 99721676cb..a50594ab27 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-DATAMONGO-2652-SNAPSHOT pom Spring Data MongoDB @@ -26,7 +26,7 @@ multi spring-data-mongodb - 2.5.0-SNAPSHOT + 2.4.0-DATACMNS-800-SNAPSHOT 4.1.1 ${mongo} 1.19 diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f0fbb601c8..2df80bf38b 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 - 3.2.0-SNAPSHOT + 3.2.0-DATAMONGO-2652-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 1a17321782..563d84bcc7 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-DATAMONGO-2652-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 0248517caf..f8ba3f3bc7 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.2.0-SNAPSHOT + 3.2.0-DATAMONGO-2652-SNAPSHOT ../pom.xml From 90884e30d1d17588c4b2fb4e487e5515e32ece21 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 10 Nov 2020 16:48:36 +0100 Subject: [PATCH 2/5] DATAMONGO-2652 - Implements CrudRepository.delete(Iterable ids). See also: DATACMNS-800. --- .../support/SimpleMongoRepository.java | 11 +++++++++- .../support/SimpleMongoRepositoryTests.java | 20 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index b00ca61a34..e934e741ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -51,6 +51,7 @@ * @author Thomas Darimont * @author Mark Paluch * @author Mehran Behnam + * @author Jens Schauder */ public class SimpleMongoRepository implements MongoRepository { @@ -182,11 +183,19 @@ public void delete(T entity) { @Override public void deleteAll(Iterable entities) { - Assert.notNull(entities, "The given Iterable of entities not be null!"); + Assert.notNull(entities, "The given Iterable of entities must not be null!"); entities.forEach(this::delete); } + @Override + public void deleteAllById(Iterable ids) { + + Assert.notNull(ids, "The given Iterable of ids must not be null!"); + + ids.forEach(this::deleteById); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.CrudRepository#deleteAll() diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 9cf066acea..1455547a48 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -15,11 +15,11 @@ */ package org.springframework.data.mongodb.repository.support; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.ExampleMatcher.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -58,6 +58,7 @@ * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author Jens Schauder */ @ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class SimpleMongoRepositoryTests { @@ -85,11 +86,11 @@ public void setUp() { leroi = new Person("Leroi", "Moore", 41); alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - all = repository.saveAll(Arrays.asList(oliver, dave, carter, boyd, stefan, leroi, alicia)); + all = repository.saveAll(asList(oliver, dave, carter, boyd, stefan, leroi, alicia)); } @Test - public void findALlFromCustomCollectionName() { + public void findAllFromCustomCollectionName() { assertThat(repository.findAll()).hasSize(all.size()); } @@ -384,7 +385,7 @@ public void saveAllUsesEntityCollection() { repository.deleteAll(); - repository.saveAll(Arrays.asList(first, second)); + repository.saveAll(asList(first, second)); assertThat(repository.findAll()).containsExactlyInAnyOrder(first, second); } @@ -435,6 +436,17 @@ public void existsShouldBePossibleInTransaction() { assertThat(exists).isTrue(); } + @Test // DATAMONGO-2652 + public void deleteAllByIds() { + + repository.deleteAllById(asList(dave.getId(), carter.getId())); + + assertThat(repository.findAll()) // + .hasSize(all.size() - 2) // + .doesNotContain(dave) // + .doesNotContain(carter); + } + private void assertThatAllReferencePersonsWereStoredCorrectly(Map references, List saved) { for (Person person : saved) { From 57e0d0f9edefbae969c8f4f656269c133cf0da8f Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 13 Nov 2020 16:08:00 +0100 Subject: [PATCH 3/5] DATAMONGO-2652 - Implements deleteAllById. See also: DATACMNS-800. --- .../SimpleReactiveMongoRepository.java | 9 +++++ .../ReactiveMongoRepositoryTests.java | 36 +++++++++++++------ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 0a1b05db3d..3b78ec1816 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -47,6 +47,7 @@ * @author Oliver Gierke * @author Christoph Strobl * @author Ruben J Garcia + * @author Jens Schauder * @since 2.0 */ public class SimpleReactiveMongoRepository implements ReactiveMongoRepository { @@ -404,6 +405,14 @@ public Mono deleteAll(Iterable entities) { return Flux.fromIterable(entities).flatMap(this::delete).then(); } + @Override + public Mono deleteAllById(Iterable ids) { + + Assert.notNull(ids, "The given Iterable of ids must not be null!"); + + return Flux.fromIterable(ids).flatMap(this::deleteById).then(); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll(org.reactivestreams.Publisher) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java index 09700dcfc1..43c0fb9962 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.repository; +import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; import static org.springframework.data.domain.Sort.Direction.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -66,7 +67,6 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor; import org.springframework.data.repository.Repository; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.ReactiveQueryMethodEvaluationContextProvider; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -77,10 +77,12 @@ * * @author Mark Paluch * @author Christoph Strobl + * @author Jens Schauder */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) public class ReactiveMongoRepositoryTests { + public static final int PERSON_COUNT = 7; static @Client MongoClient mongoClient; @Autowired ReactiveMongoTemplate template; @@ -154,17 +156,17 @@ public void setUp() throws Exception { dave = new Person("Dave", "Matthews", 42); oliver = new Person("Oliver August", "Matthews", 4); carter = new Person("Carter", "Beauford", 49); - carter.setSkills(Arrays.asList("Drums", "percussion", "vocals")); + carter.setSkills(asList("Drums", "percussion", "vocals")); Thread.sleep(10); boyd = new Person("Boyd", "Tinsley", 45); - boyd.setSkills(Arrays.asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); + boyd.setSkills(asList("Violin", "Electric Violin", "Viola", "Mandolin", "Vocals", "Guitar")); stefan = new Person("Stefan", "Lessard", 34); leroi = new Person("Leroi", "Moore", 41); alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); - repository.saveAll(Arrays.asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // - .expectNextCount(7) // + repository.saveAll(asList(oliver, carter, boyd, stefan, leroi, alicia, dave)).as(StepVerifier::create) // + .expectNextCount(PERSON_COUNT) // .verifyComplete(); } @@ -411,7 +413,7 @@ public void considersRepositoryCollectionName() { leroi.id = null; boyd.id = null; - contactRepository.saveAll(Arrays.asList(leroi, boyd)) // + contactRepository.saveAll(asList(leroi, boyd)) // .as(StepVerifier::create) // .expectNextCount(2) // .verifyComplete(); @@ -430,7 +432,7 @@ public void considersRepositoryCollectionName() { @Test // DATAMONGO-2182 public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() { - repository.findAll(person.id.in(Arrays.asList(dave.id, carter.id))) // + repository.findAll(person.id.in(asList(dave.id, carter.id))) // .collectList() // .as(StepVerifier::create) // .assertNext(actual -> { @@ -468,7 +470,7 @@ public void annotatedAggregationWithPlaceholderValue() { .contains(new PersonAggregate("Tinsley", "Boyd")) // .contains(new PersonAggregate("Beauford", "Carter")) // .contains(new PersonAggregate("Moore", "Leroi")) // - .contains(new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); + .contains(new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); }).verifyComplete(); } @@ -484,7 +486,7 @@ public void annotatedAggregationWithSort() { new PersonAggregate("Beauford", "Carter"), // new PersonAggregate("Keys", "Alicia"), // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August")), // + new PersonAggregate("Matthews", asList("Dave", "Oliver August")), // new PersonAggregate("Moore", "Leroi"), // new PersonAggregate("Tinsley", "Boyd")); }) // @@ -501,7 +503,7 @@ public void annotatedAggregationWithPageable() { assertThat(actual) // .containsExactly( // new PersonAggregate("Lessard", "Stefan"), // - new PersonAggregate("Matthews", Arrays.asList("Dave", "Oliver August"))); + new PersonAggregate("Matthews", asList("Dave", "Oliver August"))); }) // .verifyComplete(); } @@ -576,7 +578,7 @@ public void annotatedAggregationSkipsEmptyDocumentsWhenExtractingSimpleValue() { Person p3 = new Person(firstname, null); p3.setEmail("p3@example.com"); - repository.saveAll(Arrays.asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); + repository.saveAll(asList(p1, p2, p3)).then().as(StepVerifier::create).verifyComplete(); repository.projectToLastnameAndRemoveId(firstname) // .as(StepVerifier::create) // @@ -617,6 +619,18 @@ public void deleteByShouldAllowSingleDocumentRemovalCorrectly() { .verifyComplete(); } + @Test // DATAMONGO-2652 + public void deleteAllById() { + + repository.deleteAllById(asList(carter.id, dave.id)) // + .as(StepVerifier::create) // + .verifyComplete(); + + repository.count().as(StepVerifier::create) // + .expectNext(PERSON_COUNT - 2L) // + .verifyComplete(); + } + interface ReactivePersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { From 8d5ea38a48158203a42339af82c2bc1dbcb0725a Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 24 Nov 2020 11:39:39 +0100 Subject: [PATCH 4/5] DATAMONGO-2652 - deleteAllById now performs a single query. --- .../support/SimpleReactiveMongoRepository.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 3b78ec1816..460b89aa26 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -17,10 +17,8 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import java.io.Serializable; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -40,6 +38,9 @@ import com.mongodb.client.result.DeleteResult; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + /** * Reactive repository base implementation for Mongo. * @@ -410,7 +411,12 @@ public Mono deleteAllById(Iterable ids) { Assert.notNull(ids, "The given Iterable of ids must not be null!"); - return Flux.fromIterable(ids).flatMap(this::deleteById).then(); + Collection idCollection = StreamUtils.createStreamFromIterator(ids.iterator()).collect(Collectors.toList()); + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return mongoOperations + .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) + .then(); } /* From 9dab7e138f04769d93981bac6189eea450034efc Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 24 Nov 2020 14:17:37 +0100 Subject: [PATCH 5/5] DATAMONGO-2652 - deleteAll(Iterable) now performs a single query. --- .../support/SimpleReactiveMongoRepository.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index 460b89aa26..30deb56c56 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -403,7 +403,15 @@ public Mono deleteAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities must not be null!"); - return Flux.fromIterable(entities).flatMap(this::delete).then(); + Collection idCollection = StreamUtils.createStreamFromIterator(entities.iterator()) + .map(entityInformation::getId) + .collect(Collectors.toList()); + + Criteria idsInCriteria = where(entityInformation.getIdAttribute()).in(idCollection); + + return mongoOperations + .remove(new Query(idsInCriteria), entityInformation.getJavaType(), entityInformation.getCollectionName()) + .then(); } @Override