diff --git a/src/main/java/org/springframework/data/couchbase/core/ExecutableInsertByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ExecutableInsertByIdOperationSupport.java index 913630179..18fa5b382 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ExecutableInsertByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ExecutableInsertByIdOperationSupport.java @@ -36,7 +36,7 @@ public ExecutableInsertByIdOperationSupport(final CouchbaseTemplate template) { public ExecutableInsertById insertById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ExecutableInsertByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ofSeconds(0)); + DurabilityLevel.NONE, null); } static class ExecutableInsertByIdSupport implements ExecutableInsertById { diff --git a/src/main/java/org/springframework/data/couchbase/core/ExecutableReplaceByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ExecutableReplaceByIdOperationSupport.java index 1e4572cd1..888c998f4 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ExecutableReplaceByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ExecutableReplaceByIdOperationSupport.java @@ -36,7 +36,7 @@ public ExecutableReplaceByIdOperationSupport(final CouchbaseTemplate template) { public ExecutableReplaceById replaceById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ExecutableReplaceByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ZERO); + DurabilityLevel.NONE, null); } static class ExecutableReplaceByIdSupport implements ExecutableReplaceById { diff --git a/src/main/java/org/springframework/data/couchbase/core/ExecutableUpsertByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ExecutableUpsertByIdOperationSupport.java index 173bdb8cb..3c4c70c67 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ExecutableUpsertByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ExecutableUpsertByIdOperationSupport.java @@ -36,7 +36,7 @@ public ExecutableUpsertByIdOperationSupport(final CouchbaseTemplate template) { public ExecutableUpsertById upsertById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ExecutableUpsertByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ofSeconds(0)); + DurabilityLevel.NONE, null); } static class ExecutableUpsertByIdSupport implements ExecutableUpsertById { diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java index 181bbf26e..ebf6d0daa 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java @@ -15,7 +15,6 @@ */ package org.springframework.data.couchbase.core; -import org.springframework.data.couchbase.core.mapping.Document; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -42,7 +41,7 @@ public ReactiveInsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa public ReactiveInsertById insertById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ReactiveInsertByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ofSeconds(0)); + DurabilityLevel.NONE, null); } static class ReactiveInsertByIdSupport implements ReactiveInsertById { @@ -72,7 +71,7 @@ public Mono one(T object) { return Mono.just(object).flatMap(o -> { CouchbaseDocument converted = template.support().encodeEntity(o); return template.getCollection(collection).reactive() - .insert(converted.getId(), converted.export(), buildInsertOptions()).map(result -> { + .insert(converted.getId(), converted.export(), buildInsertOptions(converted)).map(result -> { Object updatedObject = template.support().applyUpdatedId(o, converted.getId()); return (T) template.support().applyUpdatedCas(updatedObject, result.cas()); }); @@ -90,19 +89,17 @@ public Flux all(Collection objects) { return Flux.fromIterable(objects).flatMap(this::one); } - private InsertOptions buildInsertOptions() { + private InsertOptions buildInsertOptions(CouchbaseDocument doc) { // CouchbaseDocument converted final InsertOptions options = InsertOptions.insertOptions(); if (persistTo != PersistTo.NONE || replicateTo != ReplicateTo.NONE) { options.durability(persistTo, replicateTo); } else if (durabilityLevel != DurabilityLevel.NONE) { options.durability(durabilityLevel); } - if (expiry != null && !expiry.isZero()) { + if (expiry != null) { options.expiry(expiry); - } else if (domainType.isAnnotationPresent(Document.class)) { - Document documentAnn = domainType.getAnnotation(Document.class); - long durationSeconds = documentAnn.expiryUnit().toSeconds(documentAnn.expiry()); - options.expiry(Duration.ofSeconds(durationSeconds)); + } else if (doc.getExpiration() != 0) { + options.expiry(Duration.ofSeconds(doc.getExpiration())); } return options; } diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java index 787bdb7dd..86442c12a 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java @@ -22,7 +22,6 @@ import java.util.Collection; import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; -import org.springframework.data.couchbase.core.mapping.Document; import org.springframework.util.Assert; import com.couchbase.client.core.msg.kv.DurabilityLevel; @@ -42,7 +41,7 @@ public ReactiveReplaceByIdOperationSupport(final ReactiveCouchbaseTemplate templ public ReactiveReplaceById replaceById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ReactiveReplaceByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ZERO); + DurabilityLevel.NONE, null); } static class ReactiveReplaceByIdSupport implements ReactiveReplaceById { @@ -72,8 +71,8 @@ public Mono one(T object) { return Mono.just(object).flatMap(o -> { CouchbaseDocument converted = template.support().encodeEntity(o); return template.getCollection(collection).reactive() - .replace(converted.getId(), converted.export(), buildReplaceOptions(o)).map(result -> - (T)template.support().applyUpdatedCas(o, result.cas())); + .replace(converted.getId(), converted.export(), buildReplaceOptions(o, converted)) + .map(result -> (T) template.support().applyUpdatedCas(o, result.cas())); }).onErrorMap(throwable -> { if (throwable instanceof RuntimeException) { return template.potentiallyConvertRuntimeException((RuntimeException) throwable); @@ -88,19 +87,17 @@ public Flux all(Collection objects) { return Flux.fromIterable(objects).flatMap(this::one); } - private ReplaceOptions buildReplaceOptions(T object) { + private ReplaceOptions buildReplaceOptions(T object, CouchbaseDocument doc) { final ReplaceOptions options = ReplaceOptions.replaceOptions(); if (persistTo != PersistTo.NONE || replicateTo != ReplicateTo.NONE) { options.durability(persistTo, replicateTo); } else if (durabilityLevel != DurabilityLevel.NONE) { options.durability(durabilityLevel); } - if (expiry != null && !expiry.isZero()) { + if (expiry != null) { options.expiry(expiry); - } else if (domainType.isAnnotationPresent(Document.class)) { - Document documentAnn = domainType.getAnnotation(Document.class); - long durationSeconds = documentAnn.expiryUnit().toSeconds(documentAnn.expiry()); - options.expiry(Duration.ofSeconds(durationSeconds)); + } else if (doc.getExpiration() != 0) { + options.expiry(Duration.ofSeconds(doc.getExpiration())); } long cas = template.support().getCas(object); options.cas(cas); diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java index c4e8fb690..8de91df0a 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java @@ -15,9 +15,6 @@ */ package org.springframework.data.couchbase.core; -import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; -import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; -import org.springframework.data.couchbase.core.mapping.Document; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -44,7 +41,7 @@ public ReactiveUpsertByIdOperationSupport(final ReactiveCouchbaseTemplate templa public ReactiveUpsertById upsertById(final Class domainType) { Assert.notNull(domainType, "DomainType must not be null!"); return new ReactiveUpsertByIdSupport<>(template, domainType, null, PersistTo.NONE, ReplicateTo.NONE, - DurabilityLevel.NONE, Duration.ofSeconds(0)); + DurabilityLevel.NONE, null); } static class ReactiveUpsertByIdSupport implements ReactiveUpsertById { @@ -74,7 +71,7 @@ public Mono one(T object) { return Mono.just(object).flatMap(o -> { CouchbaseDocument converted = template.support().encodeEntity(o); return template.getCollection(collection).reactive() - .upsert(converted.getId(), converted.export(), buildUpsertOptions()).map(result -> { + .upsert(converted.getId(), converted.export(), buildUpsertOptions(converted)).map(result -> { Object updatedObject = template.support().applyUpdatedId(o, converted.getId()); return (T) template.support().applyUpdatedCas(updatedObject, result.cas()); }); @@ -92,19 +89,17 @@ public Flux all(Collection objects) { return Flux.fromIterable(objects).flatMap(this::one); } - private UpsertOptions buildUpsertOptions() { + private UpsertOptions buildUpsertOptions(CouchbaseDocument doc) { final UpsertOptions options = UpsertOptions.upsertOptions(); if (persistTo != PersistTo.NONE || replicateTo != ReplicateTo.NONE) { options.durability(persistTo, replicateTo); } else if (durabilityLevel != DurabilityLevel.NONE) { options.durability(durabilityLevel); } - if (expiry != null && !expiry.isZero()) { + if (expiry != null) { options.expiry(expiry); - } else if (domainType.isAnnotationPresent(Document.class)) { - Document documentAnn = domainType.getAnnotation(Document.class); - long durationSeconds = documentAnn.expiryUnit().toSeconds(documentAnn.expiry()); - options.expiry(Duration.ofSeconds(durationSeconds)); + } else if (doc.getExpiration() != 0) { + options.expiry(Duration.ofSeconds(doc.getExpiration())); } return options; } diff --git a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java index f95f4ee42..2ee4e469e 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java @@ -27,9 +27,14 @@ import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_TEMPLATE; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.time.Duration; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; +import com.couchbase.client.java.manager.query.CreatePrimaryQueryIndexOptions;; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -37,14 +42,18 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.SimpleCouchbaseClientFactory; +import org.springframework.data.couchbase.core.ExecutableReplaceByIdOperation.ExecutableReplaceById; +import org.springframework.data.couchbase.core.ExecutableRemoveByIdOperation.ExecutableRemoveById; + import org.springframework.data.couchbase.domain.Config; import org.springframework.data.couchbase.domain.PersonValue; import org.springframework.data.couchbase.domain.User; import org.springframework.data.couchbase.domain.UserAnnotated; +import org.springframework.data.couchbase.domain.UserAnnotated2; +import org.springframework.data.couchbase.domain.UserAnnotated3; import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests; import org.springframework.data.couchbase.util.ClusterType; import org.springframework.data.couchbase.util.IgnoreWhen; @@ -69,6 +78,8 @@ class CouchbaseTemplateKeyValueIntegrationTests extends ClusterAwareIntegrationT static void beforeAll() { couchbaseClientFactory = new SimpleCouchbaseClientFactory(connectionString(), authenticator(), bucketName()); couchbaseClientFactory.getBucket().waitUntilReady(Duration.ofSeconds(10)); + couchbaseClientFactory.getCluster().queryIndexes().createPrimaryIndex(bucketName(), + CreatePrimaryQueryIndexOptions.createPrimaryQueryIndexOptions().ignoreIfExists(true)); } @AfterAll @@ -81,6 +92,9 @@ void beforeEach() { ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class); couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE); + couchbaseTemplate.removeByQuery(User.class).all(); + couchbaseTemplate.removeByQuery(UserAnnotated.class).all(); + couchbaseTemplate.removeByQuery(UserAnnotated2.class).all(); } @Test @@ -103,88 +117,84 @@ void upsertAndFindById() { } @Test - void upsertWithDurability() { - User user = new User(UUID.randomUUID().toString(), "firstname", "lastname"); - User modified = couchbaseTemplate.upsertById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE) - .one(user); - assertEquals(user, modified); - User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertEquals(user, found); - couchbaseTemplate.removeById().one(user.getId()); - } - - @Test - void upsertWithExpiry() { - User user = new User(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - User modified = couchbaseTemplate.upsertById(User.class).withExpiry(Duration.ofSeconds(1)).one(user); - assertEquals(user, modified); - sleepSecs(2); - User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // + void withDurability() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { + Class clazz = User.class; // for now, just User.class. There is no Durability annotation. + // insert, replace, upsert + for (OneAndAll operator : new OneAndAll[] { couchbaseTemplate.insertById(clazz), + couchbaseTemplate.replaceById(clazz), couchbaseTemplate.upsertById(clazz) }) { + // create an entity of type clazz + Constructor cons = clazz.getConstructor(String.class, String.class, String.class); + User user = (User) cons.newInstance("" + operator.getClass().getSimpleName() + "_" + clazz.getSimpleName(), + "firstname", "lastname"); + + if (clazz.equals(User.class)) { // User.java doesn't have an durability annotation + operator = (OneAndAll) ((WithDurability) operator).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE); } - } - } - @Test - void upsertWithExpiryAnnotation() { - UserAnnotated user = new UserAnnotated(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - UserAnnotated modified = couchbaseTemplate.upsertById(UserAnnotated.class).one(user); - assertEquals(user, modified); - sleepSecs(6); + // if replace, we need to insert a document to replace + if (operator instanceof ExecutableReplaceById) { + couchbaseTemplate.insertById(User.class).one(user); + } + // call to insert/replace/update + User returned = (User) operator.one(user); + assertEquals(user, returned); User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // + assertEquals(user, found); + + if (operator instanceof ExecutableReplaceById) { + couchbaseTemplate.removeById().withDurability(PersistTo.ACTIVE, ReplicateTo.NONE).one(user.getId()); + User removed = (User) couchbaseTemplate.findById(user.getClass()).one(user.getId()); + assertNull(removed, "found should have been null as document should be removed"); } } + } @Test - void replaceWithExpiry() { - User user = new User(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - User modified = couchbaseTemplate.upsertById(User.class).withExpiry(Duration.ofSeconds(1)).one(user); - couchbaseTemplate.replaceById(User.class).withExpiry(Duration.ofSeconds(1)).one(user); - assertEquals(user, modified); - sleepSecs(2); - User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // + void withExpiryAndExpiryAnnotation() + throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + // ( withExpiry(), expiry=1, expiryExpression=${myExpiry} ) X ( insert, + // replace, upsert ) + Set users = new HashSet<>(); // set of all documents we will insert + // Entity classes + for (Class clazz : new Class[] { User.class, UserAnnotated.class, UserAnnotated2.class, UserAnnotated3.class }) { + // insert, replace, upsert + for (OneAndAll operator : new OneAndAll[] { couchbaseTemplate.insertById(clazz), + couchbaseTemplate.replaceById(clazz), couchbaseTemplate.upsertById(clazz) }) { + + // create an entity of type clazz + Constructor cons = clazz.getConstructor(String.class, String.class, String.class); + User user = (User) cons.newInstance("" + operator.getClass().getSimpleName() + "_" + clazz.getSimpleName(), + "firstname", "lastname"); + + if (clazz.equals(User.class)) { // User.java doesn't have an expiry annotation + operator = (OneAndAll) ((WithExpiry) operator).withExpiry(Duration.ofSeconds(1)); + } else if (clazz.equals(UserAnnotated3.class)) { // override the expiry from the annotation with no expiry + operator = (OneAndAll) ((WithExpiry) operator).withExpiry(Duration.ofSeconds(0)); + } + + // if replace or remove, we need to insert a document to replace + if (operator instanceof ExecutableReplaceById || operator instanceof ExecutableRemoveById) { + couchbaseTemplate.insertById(User.class).one(user); + } + // call to insert/replace/update + User returned = operator.one(user); + assertEquals(user, returned); + users.add(user); } } - } - - @Test - void replaceWithExpiryAnnotation() { - UserAnnotated user = new UserAnnotated(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - UserAnnotated modified = couchbaseTemplate.upsertById(UserAnnotated.class).one(user); - modified = couchbaseTemplate.replaceById(UserAnnotated.class).one(user); - assertEquals(user, modified); - sleepSecs(6); - User found = couchbaseTemplate.findById(UserAnnotated.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // + // check that they are gone after a few seconds. + sleepSecs(4); + for (User user : users) { + User found = couchbaseTemplate.findById(user.getClass()).one(user.getId()); + if (found instanceof UserAnnotated3) { + assertNotNull(found, "found should be non null as it was set to have no expirty"); + } else { + assertNull(found, "found should have been null as document should be expired"); } } + } @Test @@ -227,10 +237,7 @@ void insertById() { User user = new User(UUID.randomUUID().toString(), "firstname", "lastname"); User inserted = couchbaseTemplate.insertById(User.class).one(user); assertEquals(user, inserted); - assertThrows(DuplicateKeyException.class, () -> couchbaseTemplate.insertById(User.class).one(user)); - couchbaseTemplate.removeById().one(user.getId()); - } @Test @@ -239,47 +246,7 @@ void insertByIdwithDurability() { User inserted = couchbaseTemplate.insertById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE) .one(user); assertEquals(user, inserted); - assertThrows(DuplicateKeyException.class, () -> couchbaseTemplate.insertById(User.class).one(user)); - couchbaseTemplate.removeById().one(user.getId()); - - } - - @Test - void insertByIdwithExpiry() { - User user = new User(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - User inserted = couchbaseTemplate.insertById(User.class).withExpiry(Duration.ofSeconds(1)).one(user); - assertEquals(user, inserted); - sleepSecs(2); - User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // ignore - } - } - - } - - @Test - void insertWithExpiryAnnotation() { - UserAnnotated user = new UserAnnotated(UUID.randomUUID().toString(), "firstname", "lastname"); - try { - UserAnnotated inserted = couchbaseTemplate.insertById(UserAnnotated.class).one(user); - assertEquals(user, inserted); - sleepSecs(6); - User found = couchbaseTemplate.findById(User.class).one(user.getId()); - assertNull(found, "found should have been null as document should be expired"); - } finally { - try { - couchbaseTemplate.removeById().one(user.getId()); - } catch (DataRetrievalFailureException e) { - // ignore - } - } } @Test @@ -292,52 +259,44 @@ void existsById() { assertEquals(user, inserted); assertTrue(couchbaseTemplate.existsById().one(id)); - couchbaseTemplate.removeById().one(user.getId()); } @Test @IgnoreWhen(clusterTypes = ClusterType.MOCKED) void saveAndFindImmutableById() { - PersonValue personValue = new PersonValue(null, 123, "f", "l"); - System.out.println("personValue: " + personValue); - // personValue = personValue.withVersion(123); + PersonValue personValue = new PersonValue(UUID.randomUUID().toString(), 123, "f", "l"); PersonValue inserted = null; PersonValue upserted = null; PersonValue replaced = null; - try { + inserted = couchbaseTemplate.insertById(PersonValue.class).one(personValue); + assertNotEquals(0, inserted.getVersion()); + PersonValue foundInserted = couchbaseTemplate.findById(PersonValue.class).one(inserted.getId()); + assertNotNull(foundInserted, "inserted personValue not found"); + assertEquals(inserted, foundInserted); + + // upsert will insert + couchbaseTemplate.removeById().one(inserted.getId()); + upserted = couchbaseTemplate.upsertById(PersonValue.class).one(inserted); + assertNotEquals(0, upserted.getVersion()); + PersonValue foundUpserted = couchbaseTemplate.findById(PersonValue.class).one(upserted.getId()); + assertNotNull(foundUpserted, "upserted personValue not found"); + assertEquals(upserted, foundUpserted); + + // upsert will replace + upserted = couchbaseTemplate.upsertById(PersonValue.class).one(inserted); + assertNotEquals(0, upserted.getVersion()); + PersonValue foundUpserted2 = couchbaseTemplate.findById(PersonValue.class).one(upserted.getId()); + assertNotNull(foundUpserted2, "upserted personValue not found"); + assertEquals(upserted, foundUpserted2); + + replaced = couchbaseTemplate.replaceById(PersonValue.class).one(upserted); + assertNotEquals(0, replaced.getVersion()); + PersonValue foundReplaced = couchbaseTemplate.findById(PersonValue.class).one(replaced.getId()); + assertNotNull(foundReplaced, "replaced personValue not found"); + assertEquals(replaced, foundReplaced); - inserted = couchbaseTemplate.insertById(PersonValue.class).one(personValue); - assertNotEquals(0, inserted.getVersion()); - PersonValue foundInserted = couchbaseTemplate.findById(PersonValue.class).one(inserted.getId()); - assertNotNull(foundInserted, "inserted personValue not found"); - assertEquals(inserted, foundInserted); - - // upsert will be inserted - couchbaseTemplate.removeById().one(inserted.getId()); - upserted = couchbaseTemplate.upsertById(PersonValue.class).one(inserted); - assertNotEquals(0, upserted.getVersion()); - PersonValue foundUpserted = couchbaseTemplate.findById(PersonValue.class).one(upserted.getId()); - assertNotNull(foundUpserted, "upserted personValue not found"); - assertEquals(upserted, foundUpserted); - - // upsert will be replaced - upserted = couchbaseTemplate.upsertById(PersonValue.class).one(inserted); - assertNotEquals(0, upserted.getVersion()); - PersonValue foundUpserted2 = couchbaseTemplate.findById(PersonValue.class).one(upserted.getId()); - assertNotNull(foundUpserted2, "upserted personValue not found"); - assertEquals(upserted, foundUpserted2); - - replaced = couchbaseTemplate.replaceById(PersonValue.class).one(upserted); - assertNotEquals(0, replaced.getVersion()); - PersonValue foundReplaced = couchbaseTemplate.findById(PersonValue.class).one(replaced.getId()); - assertNotNull(foundReplaced, "replaced personValue not found"); - assertEquals(replaced, foundReplaced); - - } finally { - couchbaseTemplate.removeById().one(inserted.getId()); - } } private void sleepSecs(int i) { diff --git a/src/test/java/org/springframework/data/couchbase/domain/UserAnnotated3.java b/src/test/java/org/springframework/data/couchbase/domain/UserAnnotated3.java new file mode 100644 index 000000000..d3caa0979 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/domain/UserAnnotated3.java @@ -0,0 +1,35 @@ +/* + * Copyright 2020 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.couchbase.domain; + +import java.util.concurrent.TimeUnit; + +import org.springframework.data.couchbase.core.mapping.Document; + +/** + * Annotated User entity for tests + * + * @author Michael Reiche + */ + +@Document(expiry=1, expiryUnit = TimeUnit.SECONDS) +public class UserAnnotated3 extends User { + + public UserAnnotated3(String id, String firstname, String lastname) { + super(id, firstname, lastname); + } +}