diff --git a/src/main/asciidoc/entity.adoc b/src/main/asciidoc/entity.adoc index 057b9e2e7..b713edfb0 100644 --- a/src/main/asciidoc/entity.adoc +++ b/src/main/asciidoc/entity.adoc @@ -375,7 +375,7 @@ public class User { If you load a document through the template or repository, the version field will be automatically populated with the current CAS value. It is important to note that you shouldn't access the field or even change it on your own. -Once you save the document back, it will either succeed or fail with a `DataIntegrityViolationException`. +Once you save the document back, it will either succeed or fail with a `OptimisticLockingFailureException`. If you get such an exception, the further approach depends on what you want to achieve application wise. You should either retry the complete load-update-write cycle or propagate the error to the upper layers for proper handling. diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java index 264c8334e..e4d22669e 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java @@ -25,6 +25,7 @@ import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.dao.OptimisticLockingFailureException;; import org.springframework.dao.QueryTimeoutException; import org.springframework.dao.TransientDataAccessResourceException; import org.springframework.dao.support.PersistenceExceptionTranslator; @@ -66,8 +67,11 @@ public final DataAccessException translateExceptionIfPossible(final RuntimeExcep return new DataRetrievalFailureException(ex.getMessage(), ex); } - if (ex instanceof CasMismatchException || ex instanceof ConcurrentModificationException - || ex instanceof ReplicaNotConfiguredException || ex instanceof DurabilityLevelNotAvailableException + if (ex instanceof CasMismatchException || ex instanceof ConcurrentModificationException) { + return new OptimisticLockingFailureException(ex.getMessage(), ex); + } + + if ( ex instanceof ReplicaNotConfiguredException || ex instanceof DurabilityLevelNotAvailableException || ex instanceof DurabilityImpossibleException || ex instanceof DurabilityAmbiguousException) { return new DataIntegrityViolationException(ex.getMessage(), ex); } 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 ec405b741..2e9f14d1a 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java @@ -39,6 +39,7 @@ import org.junit.jupiter.api.Test; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.couchbase.core.ExecutableFindByIdOperation.ExecutableFindById; import org.springframework.data.couchbase.core.ExecutableRemoveByIdOperation.ExecutableRemoveById; import org.springframework.data.couchbase.core.ExecutableReplaceByIdOperation.ExecutableReplaceById; @@ -137,7 +138,7 @@ void upsertAndFindById() { User badUser = new User(user.getId(), user.getFirstname(), user.getLastname()); badUser.setVersion(12345678); - assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.replaceById(User.class).one(badUser)); + assertThrows(OptimisticLockingFailureException.class, () -> couchbaseTemplate.replaceById(User.class).one(badUser)); User found = couchbaseTemplate.findById(User.class).one(user.getId()); assertEquals(modified, found); @@ -347,7 +348,7 @@ void upsertAndRemoveById() { // careful now - user and modified are the same object. The object has the new cas (@Version version) Long savedCas = modified.getVersion(); modified.setVersion(123); - assertThrows(DataIntegrityViolationException.class, () -> couchbaseTemplate.removeById() + assertThrows(OptimisticLockingFailureException.class, () -> couchbaseTemplate.removeById() .withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId())); modified.setVersion(savedCas); couchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified)) diff --git a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java index 2bb669cbb..8fd709ec5 100644 --- a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java @@ -37,8 +37,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.couchbase.core.ReactiveFindByIdOperation.ReactiveFindById; import org.springframework.data.couchbase.core.ReactiveRemoveByIdOperation.ReactiveRemoveById; import org.springframework.data.couchbase.core.ReactiveReplaceByIdOperation.ReactiveReplaceById; @@ -130,7 +130,7 @@ void upsertAndFindById() { User badUser = new User(user.getId(), user.getFirstname(), user.getLastname()); badUser.setVersion(12345678); - assertThrows(DataIntegrityViolationException.class, + assertThrows(OptimisticLockingFailureException.class, () -> reactiveCouchbaseTemplate.replaceById(User.class).one(badUser).block()); User found = reactiveCouchbaseTemplate.findById(User.class).one(user.getId()).block(); @@ -285,7 +285,7 @@ void upsertAndRemoveById() { // careful now - user and modified are the same object. The object has the new cas (@Version version) Long savedCas = modified.getVersion(); modified.setVersion(123); - assertThrows(DataIntegrityViolationException.class, () -> reactiveCouchbaseTemplate.removeById() + assertThrows(OptimisticLockingFailureException.class, () -> reactiveCouchbaseTemplate.removeById() .withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()).block()); modified.setVersion(savedCas); reactiveCouchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified)) diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java index 384f8234e..84f63a5d0 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryKeyValueIntegrationTests.java @@ -35,8 +35,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.domain.Airline; @@ -110,7 +110,7 @@ void saveReplaceUpsertInsert() { user.setVersion(0); assertThrows(DuplicateKeyException.class, () -> userRepository.save(user)); user.setVersion(saveVersion + 1); - assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user)); + assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user)); userRepository.delete(user); // Airline does not have a version 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 79f709d84..55212e3c0 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -55,8 +55,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.auditing.DateTimeProvider; import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; @@ -566,7 +566,7 @@ public void testCas() { userRepository.save(user); long saveVersion = user.getVersion(); user.setVersion(user.getVersion() - 1); - assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user)); + assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user)); user.setVersion(saveVersion); userRepository.save(user); userRepository.delete(user); diff --git a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java index 9192639d7..46169ba59 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryKeyValueIntegrationTests.java @@ -28,8 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.auditing.DateTimeProvider; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; import org.springframework.data.couchbase.domain.Airline; @@ -72,7 +72,7 @@ void saveReplaceUpsertInsert() { user.setVersion(0); assertThrows(DuplicateKeyException.class, () -> userRepository.save(user).block()); user.setVersion(saveVersion + 1); - assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user).block()); + assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user).block()); userRepository.delete(user); // Airline does not have a version 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 a6c7bfb19..725a93b6a 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/ReactiveCouchbaseRepositoryQueryIntegrationTests.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import org.springframework.dao.OptimisticLockingFailureException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -40,7 +41,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; @@ -120,7 +120,7 @@ public void testCas() { userRepository.save(user).block(); long saveVersion = user.getVersion(); user.setVersion(user.getVersion() - 1); - assertThrows(DataIntegrityViolationException.class, () -> userRepository.save(user).block()); + assertThrows(OptimisticLockingFailureException.class, () -> userRepository.save(user).block()); user.setVersion(saveVersion); userRepository.save(user).block(); userRepository.delete(user).block();