Skip to content

Commit c158cda

Browse files
committed
DATACOUCH-623 - Add replace() method to CouchbaseRepository for CAS usage.
1 parent e72cdba commit c158cda

File tree

6 files changed

+74
-4
lines changed

6 files changed

+74
-4
lines changed

src/main/java/org/springframework/data/couchbase/repository/CouchbaseRepository.java

+4
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ public interface CouchbaseRepository<T, ID> extends PagingAndSortingRepository<T
4343
@Override
4444
List<T> findAllById(Iterable<ID> iterable);
4545

46+
<S extends T> S replace(S var1);
47+
48+
<S extends T> Iterable<S> replaceAll(Iterable<S> var1);
49+
4650
}

src/main/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepository.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
*/
1616
package org.springframework.data.couchbase.repository;
1717

18+
import org.reactivestreams.Publisher;
1819
import org.springframework.data.repository.NoRepositoryBean;
1920
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
21+
import reactor.core.publisher.Flux;
22+
import reactor.core.publisher.Mono;
2023

2124
/**
2225
* Couchbase-specific {@link ReactiveSortingRepository} implementation.
@@ -27,4 +30,10 @@
2730
@NoRepositoryBean
2831
public interface ReactiveCouchbaseRepository<T, ID> extends ReactiveSortingRepository<T, ID> {
2932

30-
}
33+
public <S extends T> Mono<S> replace(final S entity);
34+
35+
public <S extends T> Flux<S> replaceAll(final Iterable<S> entities);
36+
37+
public <S extends T> Flux<S> replaceAll(final Publisher<S> entityStream);
38+
39+
}

src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java

+15
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,21 @@ public <S extends T> Iterable<S> saveAll(final Iterable<S> entities) {
8686
.all(Streamable.of(entities).toList());
8787
}
8888

89+
@Override
90+
@SuppressWarnings("unchecked")
91+
public <S extends T> S replace(final S entity) {
92+
Assert.notNull(entity, "Entity must not be null!");
93+
return (S) couchbaseOperations.replaceById(entityInformation.getJavaType()).one(entity);
94+
}
95+
96+
@Override
97+
@SuppressWarnings("unchecked")
98+
public <S extends T> Iterable<S> replaceAll(final Iterable<S> entities) {
99+
Assert.notNull(entities, "The given Iterable of entities must not be null!");
100+
return (Iterable<S>) couchbaseOperations.replaceById(entityInformation.getJavaType())
101+
.all(Streamable.of(entities).toList());
102+
}
103+
89104
@Override
90105
public Optional<T> findById(final ID id) {
91106
Assert.notNull(id, "The given id must not be null!");

src/main/java/org/springframework/data/couchbase/repository/support/SimpleReactiveCouchbaseRepository.java

+20
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ public <S extends T> Mono<S> save(final S entity) {
8080
return (Mono<S>) operations.upsertById(entityInformation.getJavaType()).one(entity);
8181
}
8282

83+
@SuppressWarnings("unchecked")
84+
public <S extends T> Mono<S> replace(final S entity) {
85+
Assert.notNull(entity, "Entity must not be null!");
86+
return (Mono<S>) operations.replaceById(entityInformation.getJavaType()).one(entity);
87+
}
88+
8389
@Override
8490
public Flux<T> findAll(final Sort sort) {
8591
return findAll(new Query().with(sort));
@@ -99,6 +105,20 @@ public <S extends T> Flux<S> saveAll(final Publisher<S> entityStream) {
99105
return Flux.from(entityStream).flatMap(this::save);
100106
}
101107

108+
@SuppressWarnings("unchecked")
109+
@Override
110+
public <S extends T> Flux<S> replaceAll(final Iterable<S> entities) {
111+
Assert.notNull(entities, "The given Iterable of entities must not be null!");
112+
return (Flux<S>) operations.replaceById(entityInformation.getJavaType()).all(Streamable.of(entities).toList());
113+
}
114+
115+
@SuppressWarnings("unchecked")
116+
@Override
117+
public <S extends T> Flux<S> replaceAll(final Publisher<S> entityStream) {
118+
Assert.notNull(entityStream, "The given Iterable of entities must not be null!");
119+
return Flux.from(entityStream).flatMap(this::replace);
120+
}
121+
102122
@SuppressWarnings("unchecked")
103123
@Override
104124
public Mono<T> findById(final ID id) {

src/test/java/org/springframework/data/couchbase/domain/UserRepository.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.util.List;
2020

21+
import com.couchbase.client.java.json.JsonArray;
22+
import org.springframework.data.couchbase.repository.CouchbaseRepository;
2123
import org.springframework.data.couchbase.repository.Query;
2224
import org.springframework.data.repository.PagingAndSortingRepository;
2325
import org.springframework.data.repository.query.Param;
@@ -30,10 +32,14 @@
3032
* @author Michael Reiche
3133
*/
3234
@Repository
33-
public interface UserRepository extends PagingAndSortingRepository<User, String> {
35+
public interface UserRepository extends CouchbaseRepository<User, String> {
3436

3537
List<User> findByFirstname(String firstname);
3638

39+
List<User> findByFirstnameIn(String... firstnames);
40+
41+
List<User> findByFirstnameIn(JsonArray firstnames);
42+
3743
List<User> findByFirstnameAndLastname(String firstname, String lastname);
3844

3945
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and firstname = $1 and lastname = $2")

src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@
3131
import org.junit.jupiter.api.Test;
3232
import org.springframework.beans.factory.annotation.Autowired;
3333
import org.springframework.context.annotation.Configuration;
34+
import org.springframework.dao.DataIntegrityViolationException;
3435
import org.springframework.data.couchbase.CouchbaseClientFactory;
3536
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
3637
import org.springframework.data.couchbase.domain.Airport;
3738
import org.springframework.data.couchbase.domain.AirportRepository;
39+
import org.springframework.data.couchbase.domain.User;
40+
import org.springframework.data.couchbase.domain.UserRepository;
3841
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
3942
import org.springframework.data.couchbase.util.Capabilities;
4043
import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests;
@@ -58,6 +61,8 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
5861

5962
@Autowired AirportRepository airportRepository;
6063

64+
@Autowired UserRepository userRepository;
65+
6166
@BeforeEach
6267
void beforeEach() {
6368
try {
@@ -118,6 +123,17 @@ void findBySimpleProperty() {
118123

119124
}
120125

126+
@Test
127+
public void testCas() {
128+
129+
User user = new User("1", "Dave", "Wilson");
130+
userRepository.save(user);
131+
user.setVersion(user.getVersion() - 1);
132+
assertThrows(DataIntegrityViolationException.class, () -> userRepository.replace(user));
133+
userRepository.delete(user);
134+
135+
}
136+
121137
@Test
122138
void count() {
123139
String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" };
@@ -132,8 +148,8 @@ void count() {
132148
airportRepository.save(airport);
133149
}
134150

135-
Long count = airportRepository.countFancyExpression( Arrays.asList("JFK"), Arrays.asList("jfk"), false);
136-
assertEquals( 1, count);
151+
Long count = airportRepository.countFancyExpression(Arrays.asList("JFK"), Arrays.asList("jfk"), false);
152+
assertEquals(1, count);
137153

138154
long airportCount = airportRepository.count();
139155
assertEquals(7, airportCount);

0 commit comments

Comments
 (0)