Correct behavior of NOOP deletes to match the specification in CrudRepository.

Delete operations that receive a version attribute throw an `OptimisticFailureException` when they delete zero rows.
Otherwise, the NOOP delete gets silently ignored.

Note that save operations that are determined to be an update because the aggregate is not new will still throw an `IncorrectUpdateSemanticsDataAccessException` if they fail to update any row.
This is somewhat asymmetric to the delete-behaviour.
But with a delete the intended result is achieved: the aggregate is gone from the database.
For save operations the intended result is not achieved, hence the exception.

Closes #1313
Original pull request: #1314.
See https://github.com/spring-projects/spring-data-commons/issues/2651
This commit is contained in:
Jens Schauder
2022-08-25 16:15:27 +02:00
committed by Mark Paluch
parent f5989e1cfc
commit 7b1f680a26
3 changed files with 33 additions and 7 deletions

View File

@@ -866,11 +866,11 @@ class JdbcAggregateTemplateIntegrationTests {
assertThatThrownBy(() -> template.save(new AggregateWithImmutableVersion(id, 0L)))
.describedAs("saving an aggregate with an outdated version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
assertThatThrownBy(() -> template.save(new AggregateWithImmutableVersion(id, 2L)))
.describedAs("saving an aggregate with a future version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
}
@Test // GH-1137
@@ -915,12 +915,12 @@ class JdbcAggregateTemplateIntegrationTests {
assertThatThrownBy(
() -> template.delete(new AggregateWithImmutableVersion(id, 0L), AggregateWithImmutableVersion.class))
.describedAs("deleting an aggregate with an outdated version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
assertThatThrownBy(
() -> template.delete(new AggregateWithImmutableVersion(id, 2L), AggregateWithImmutableVersion.class))
.describedAs("deleting an aggregate with a future version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
// This should succeed
template.delete(aggregate, AggregateWithImmutableVersion.class);
@@ -1060,12 +1060,12 @@ class JdbcAggregateTemplateIntegrationTests {
reloadedAggregate.setVersion(toConcreteNumber.apply(initialId));
assertThatThrownBy(() -> template.save(reloadedAggregate))
.withFailMessage("saving an aggregate with an outdated version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
reloadedAggregate.setVersion(toConcreteNumber.apply(initialId + 2));
assertThatThrownBy(() -> template.save(reloadedAggregate))
.withFailMessage("saving an aggregate with a future version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
.isInstanceOf(OptimisticLockingFailureException.class);
}
private Long count(String tableName) {