From f672d998e187802108b94391294477c5751b30b3 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Nov 2020 10:43:27 +0100 Subject: [PATCH 1/2] DATACOUCH-650 - Prepare branch --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 87b60dfdb..6d01c5e94 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-couchbase - 4.2.0-SNAPSHOT + 4.2.0-DATACOUCH-650-SNAPSHOT Spring Data Couchbase Spring Data integration for Couchbase From 1f87ed20bf5404de40fac1bcf840804d8533ca84 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Thu, 12 Nov 2020 13:40:30 +0100 Subject: [PATCH 2/2] DATACOUCH-650 - Implements deleteById(Iterable ids). --- pom.xml | 8 ++- .../support/SimpleCouchbaseRepository.java | 7 +++ .../SimpleReactiveCouchbaseRepository.java | 6 ++ ...chbaseRepositoryQueryIntegrationTests.java | 26 ++++++++- ...chbaseRepositoryQueryIntegrationTests.java | 56 +++++++++++++------ 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 6d01c5e94..0bbecc7a2 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 3.0.9 3.0.9 - 2.5.0-SNAPSHOT + 2.4.0-DATACMNS-800-SNAPSHOT spring.data.couchbase @@ -161,6 +161,12 @@ test + + io.projectreactor + reactor-test + test + + org.jetbrains.kotlin diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java index 7444e9162..5e8d569f8 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java @@ -42,6 +42,7 @@ * * @author Michael Nitschinger * @author Mark Paluch + * @author Jens Schauder */ public class SimpleCouchbaseRepository implements CouchbaseRepository { @@ -130,6 +131,12 @@ public void deleteAll(final Iterable entities) { couchbaseOperations.removeById().all(Streamable.of(entities).map(entityInformation::getId).toList()); } + @Override + public void deleteAllById(Iterable ids) { + Assert.notNull(ids, "The given Iterable of ids must not be null!"); + couchbaseOperations.removeById().all(Streamable.of(ids).map(Objects::toString).toList()); + } + @Override public long count() { return couchbaseOperations.findByQuery(entityInformation.getJavaType()).consistentWith(buildQueryScanConsistency()) diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleReactiveCouchbaseRepository.java b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleReactiveCouchbaseRepository.java index 94a77a3ed..fe2bcd96f 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleReactiveCouchbaseRepository.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleReactiveCouchbaseRepository.java @@ -44,6 +44,7 @@ * @author Christoph Strobl * @author David Kelly * @author Douglas Six + * @author Jens Schauder * @since 3.0 */ public class SimpleReactiveCouchbaseRepository implements ReactiveCouchbaseRepository { @@ -185,6 +186,11 @@ public Mono deleteAll(final Publisher entityStream) { return Flux.from(entityStream).flatMap(this::delete).single(); } + @Override + public Mono deleteAllById(final Iterable ids) { + return operations.removeById().all(Streamable.of(ids).map(Object::toString).toList()).then(); + } + @SuppressWarnings("unchecked") @Override public Mono count() { diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java index dc98617ce..4c14ce1d2 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -16,6 +16,8 @@ package org.springframework.data.couchbase.repository; +import static java.util.Arrays.*; +import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; import java.util.ArrayList; @@ -26,6 +28,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -47,6 +50,7 @@ import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests; import org.springframework.data.couchbase.util.ClusterType; import org.springframework.data.couchbase.util.IgnoreWhen; +import org.springframework.data.util.StreamUtils; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import com.couchbase.client.core.error.IndexExistsException; @@ -56,6 +60,7 @@ * * @author Michael Nitschinger * @author Michael Reiche + * @author Jens Schauder */ @SpringJUnitConfig(CouchbaseRepositoryQueryIntegrationTests.Config.class) @IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED) @@ -170,7 +175,7 @@ void count() { airportRepository.save(airport); } - Long count = airportRepository.countFancyExpression(Arrays.asList("JFK"), Arrays.asList("jfk"), false); + Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false); assertEquals(1, count); long airportCount = airportRepository.count(); @@ -277,6 +282,25 @@ void threadSafeStringParametersTest() throws Exception { } } + @Test // DATACOUCH-650 + void deleteAllById() { + + Airport vienna = new Airport("airports::vie", "vie", "LOWW"); + Airport frankfurt = new Airport("airports::fra", "fra", "EDDF"); + Airport losAngeles = new Airport("airports::lax", "lax", "KLAX"); + + try { + airportRepository.saveAll(asList(vienna, frankfurt, losAngeles)); + + airportRepository.deleteAllById(asList(vienna.getId(), losAngeles.getId())); + + + assertThat(airportRepository.findAll()).containsExactly(frankfurt); + } finally { + airportRepository.deleteAll(); + } + } + private void sleep(int millis) { try { Thread.sleep(millis); // so they are executed out-of-order diff --git a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java index 12285ae0c..935c79d9f 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java @@ -16,15 +16,7 @@ package org.springframework.data.couchbase.repository; -import static org.junit.jupiter.api.Assertions.*; - -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.stream.Collectors; - +import com.couchbase.client.core.error.IndexExistsException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -43,8 +35,18 @@ import org.springframework.data.couchbase.util.ClusterType; import org.springframework.data.couchbase.util.IgnoreWhen; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import reactor.test.StepVerifier; -import com.couchbase.client.core.error.IndexExistsException; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.Collectors; + +import static java.util.Arrays.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; /** * template class for Reactive Couchbase operations @@ -56,10 +58,13 @@ @IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED) public class ReactiveCouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegrationTests { - @Autowired CouchbaseClientFactory clientFactory; + @Autowired + CouchbaseClientFactory clientFactory; - @Autowired ReactiveAirportRepository airportRepository; // intellij flags "Could not Autowire", but it runs ok. - @Autowired ReactiveUserRepository userRepository; // intellij flags "Could not Autowire", but it runs ok. + @Autowired + ReactiveAirportRepository airportRepository; // intellij flags "Could not Autowire", but it runs ok. + @Autowired + ReactiveUserRepository userRepository; // intellij flags "Could not Autowire", but it runs ok. @BeforeEach void beforeEach() { @@ -93,9 +98,9 @@ void findBySimpleProperty() { vie = new Airport("airports::vie", "vie", "loww"); airportRepository.save(vie).block(); List airports1 = airportRepository.findAllByIata("vie").collectList().block(); - assertEquals(1,airports1.size()); + assertEquals(1, airports1.size()); List airports2 = airportRepository.findAllByIata("vie").collectList().block(); - assertEquals(1,airports2.size()); + assertEquals(1, airports2.size()); } finally { airportRepository.delete(vie).block(); } @@ -114,7 +119,7 @@ public void testCas() { @Test void count() { - String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" }; + String[] iatas = {"JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX"}; Future[] future = new Future[iatas.length]; ExecutorService executorService = Executors.newFixedThreadPool(iatas.length); try { @@ -148,6 +153,25 @@ void count() { } } + @Test + // DATACOUCH-650 + void deleteAllById() { + + Airport vienna = new Airport("airports::vie", "vie", "LOWW"); + Airport frankfurt = new Airport("airports::fra", "fra", "EDDF"); + Airport losAngeles = new Airport("airports::lax", "lax", "KLAX"); + + try { + airportRepository.saveAll(asList(vienna, frankfurt, losAngeles)).as(StepVerifier::create).verifyComplete(); + + airportRepository.deleteAllById(asList(vienna.getId(), losAngeles.getId())).as(StepVerifier::create).verifyComplete(); + + airportRepository.findAll().as(StepVerifier::create).expectNext(frankfurt).verifyComplete(); + } finally { + airportRepository.deleteAll(); + } + } + @Configuration @EnableReactiveCouchbaseRepositories("org.springframework.data.couchbase") static class Config extends AbstractCouchbaseConfiguration {