diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/DynamicInvocationHandler.java b/src/main/java/org/springframework/data/couchbase/repository/support/DynamicInvocationHandler.java index f888e0e2a..4f7c32bfa 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/DynamicInvocationHandler.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/DynamicInvocationHandler.java @@ -110,7 +110,8 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl .map(o -> o == null ? null : (o.getClass() == entityInformation.getJavaType() ? Object.class : o.getClass())) .toArray(Class[]::new); // the CouchbaseRepository methods - findById(id) etc - will have a parameter type of Object instead of ID - if (method.getName().endsWith("ById") && args.length == 1) { + // but deleteByAllId first parameter will be an iterable. + if (method.getName().endsWith("ById") && args.length == 1 && ! Iterable.class.isAssignableFrom(paramTypes[0]) ) { paramTypes[0] = Object.class; } } 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 ed7b86b6a..2b2b22da0 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 @@ -73,7 +73,7 @@ public S save(S entity) { String scopeName = getScope(); String collectionName = getCollection(); // clear out the PseudoArgs here as whatever is called by operations.save() could be in a different thread. - // not that this will also clear out Options, but that's ok as any options would not work + // note that this will also clear out Options, but that's ok as any options would not work // with all of insert/upsert/replace. If Options are needed, use template.insertById/upsertById/replaceById getReactiveTemplate().setPseudoArgs(null); return operations.save(entity, scopeName, collectionName); @@ -82,7 +82,13 @@ public S save(S entity) { @Override public Iterable saveAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities must not be null!"); - return Streamable.of(entities).stream().map((e) -> save(e)).collect(StreamUtils.toUnmodifiableList()); + String scopeName = getScope(); + String collectionName = getCollection(); + // clear out the PseudoArgs here as whatever is called by operations.save() could be in a different thread. + // note that this will also clear out Options, but that's ok as any options would not work + // with all of insert/upsert/replace. If Options are needed, use template.insertById/upsertById/replaceById + getReactiveTemplate().setPseudoArgs(null); + return Streamable.of(entities).stream().map((e) -> operations.save(e,scopeName, collectionName)).collect(StreamUtils.toUnmodifiableList()); } @Override 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 177572967..7f7d8bba9 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 @@ -77,7 +77,7 @@ public Mono save(S entity) { String scopeName = getScope(); String collectionName = getCollection(); // clear out the PseudoArgs here as whatever is called by operations.save() could be in a different thread. - // not that this will also clear out Options, but that's ok as any options would not work + // note that this will also clear out Options, but that's ok as any options would not work // with all of insert/upsert/replace. If Options are needed, use template.insertById/upsertById/replaceById getReactiveTemplate().setPseudoArgs(null); return operations.save(entity, scopeName, collectionName); @@ -88,6 +88,10 @@ public Flux saveAll(Iterable entities) { Assert.notNull(entities, "The given Iterable of entities must not be null!"); String scope = getScope(); String collection = getCollection(); + // clear out the PseudoArgs here as whatever is called by operations.save() could be in a different thread. + // note that this will also clear out Options, but that's ok as any options would not work + // with all of insert/upsert/replace. If Options are needed, use template.insertById/upsertById/replaceById + getReactiveTemplate().setPseudoArgs(null); return Flux.fromIterable(entities).flatMap(e -> save(e, scope, collection)); } @@ -96,6 +100,10 @@ public Flux saveAll(Publisher entityStream) { Assert.notNull(entityStream, "The given Iterable of entities must not be null!"); String scope = getScope(); String collection = getCollection(); + // clear out the PseudoArgs here as whatever is called by operations.save() could be in a different thread. + // note that this will also clear out Options, but that's ok as any options would not work + // with all of insert/upsert/replace. If Options are needed, use template.insertById/upsertById/replaceById + getReactiveTemplate().setPseudoArgs(null); return Flux.from(entityStream).flatMap(e -> save(e, scope, collection)); } diff --git a/src/test/java/org/springframework/data/couchbase/repository/query/CouchbaseRepositoryQueryCollectionIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/query/CouchbaseRepositoryQueryCollectionIntegrationTests.java index a04523b1c..28849d27b 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/query/CouchbaseRepositoryQueryCollectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/query/CouchbaseRepositoryQueryCollectionIntegrationTests.java @@ -17,6 +17,8 @@ import static com.couchbase.client.core.io.CollectionIdentifier.DEFAULT_SCOPE; import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -443,4 +445,23 @@ void stringDeleteWithMethodAnnotationTest() { } } + + @Test // DATACOUCH-650, SDC-1939 + void deleteAllById() { + + Airport vienna = new Airport("airports::vie", "vie", "LOWW"); + Airport frankfurt = new Airport("airports::fra", "fra", "EDDZ"); + Airport losAngeles = new Airport("airports::lax", "lax", "KLAX"); + AirportRepository ar = airportRepository.withScope(scopeName).withCollection(collectionName); + try { + ar.saveAll(asList(vienna, frankfurt, losAngeles)); + List airports = ar.findAllById(asList(vienna.getId(), losAngeles.getId())); + assertEquals(2, airports.size()); + ar.deleteAllById(asList(vienna.getId(), losAngeles.getId())); + assertThat(ar.findAll()).containsExactly(frankfurt); + ar.deleteAll(asList(frankfurt)); + } finally { + ar.deleteAll(); + } + } } diff --git a/src/test/java/org/springframework/data/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java index 980c7f2b8..677981a7a 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/query/ReactiveCouchbaseRepositoryQueryCollectionIntegrationTests.java @@ -15,9 +15,12 @@ */ package org.springframework.data.couchbase.repository.query; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.springframework.data.couchbase.domain.AirportRepository; import reactor.core.Disposable; import java.util.List; @@ -298,4 +301,23 @@ void stringDeleteWithMethodAnnotationTest() { } } + @Test // DATACOUCH-650, SDC-1939 + void deleteAllById() { + + Airport vienna = new Airport("airports::vie", "vie", "LOWW"); + Airport frankfurt = new Airport("airports::fra", "fra", "EDDZ"); + Airport losAngeles = new Airport("airports::lax", "lax", "KLAX"); + ReactiveAirportRepository ar = reactiveAirportRepository.withScope(scopeName).withCollection(collectionName); + try { + ar.saveAll(asList(vienna, frankfurt, losAngeles)).blockLast(); + List airports = ar.findAllById(asList(vienna.getId(), losAngeles.getId())).collectList().block(); + assertEquals(2, airports.size()); + ar.deleteAllById(asList(vienna.getId(), losAngeles.getId())).block(); + assertThat(ar.findAll().collectList().block()).containsExactly(frankfurt); + ar.deleteAll(asList(frankfurt)).block(); + } finally { + ar.deleteAll().block(); + } + } + }