DATACASS-576 - Add support for Optimistic Locking.
We now support Optimistic Locking for insert, update and delete operations leveraging Cassandra's lightweight transaction support. Modifying statements are enhanced with IF conditions to conditionally insert and modify rows and to prevent concurrent modifications by throwing OptimisticLockingFailureException.
@Table
class Person {
@Id String id;
String firstname;
String lastname;
@Version Long version;
}
Person daenerys = template.insert(new Person("Daenerys"));
Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class);
daenerys.setLastname("Targaryen");
template.save(daenerys);
template.save(tmp); // throws OptimisticLockingFailureException
This commit is contained in:
@@ -10,6 +10,7 @@ This chapter summarizes changes and new features for each release.
|
||||
* Kotlin Coroutine extensions for `ReactiveFluentCassandraOperations`.
|
||||
* Lightweight transaction support via `DeleteOptions` using the Template API.
|
||||
* Filter conditions for lightweight transaction update and delete (`UPDATE … IF <condition>`, `DELETE … IF <condition>`).
|
||||
* Optimistic Locking support.
|
||||
|
||||
[[new-features.2-1-0]]
|
||||
== What's new in Spring Data for Apache Cassandra 2.1
|
||||
|
||||
@@ -1167,6 +1167,45 @@ You can use the following overloaded methods to remove an object from the databa
|
||||
* `T` *delete* `(T entity, QueryOptions queryOptions)`: Deletes the given object applying `QueryOptions`.
|
||||
* `boolean` *deleteById* `(Object id, Class<?> entityClass)`: Deletes the object using the given Id.
|
||||
|
||||
[[cassandra.template.optimistic-locking]]
|
||||
=== Optimistic Locking
|
||||
|
||||
The `@Version` annotation provides syntax similar to that of JPA in the context of Cassandra and makes sure updates are only applied to rows with a matching version.
|
||||
Optimistic Locking leverages Cassandra's lightweight transactions to conditionally insert, update and delete rows.
|
||||
Therefore, `INSERT` statements are executed with the `IF NOT EXISTS` condition.
|
||||
For updates and deletes, the actual value of the version property is added to the `UPDATE` condition in such a way that the modification does not have any effect if another operation altered the row in the meantime.
|
||||
In that case, an `OptimisticLockingFailureException` is thrown.
|
||||
The following example shows these features:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Table
|
||||
class Person {
|
||||
|
||||
@Id String id;
|
||||
String firstname;
|
||||
String lastname;
|
||||
@Version Long version;
|
||||
}
|
||||
|
||||
Person daenerys = template.insert(new Person("Daenerys")); <1>
|
||||
|
||||
Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class); <2>
|
||||
|
||||
daenerys.setLastname("Targaryen");
|
||||
template.save(daenerys); <3>
|
||||
|
||||
template.save(tmp); // throws OptimisticLockingFailureException <4>
|
||||
----
|
||||
<1> Intially insert document. `version` is set to `0`.
|
||||
<2> Load the just inserted document. `version` is still `0`.
|
||||
<3> Update the document with `version = 0`. Set the `lastname` and bump `version` to `1`.
|
||||
<4> Try to update the previously loaded document that still has `version = 0`. The operation fails with an `OptimisticLockingFailureException`, as the current `version` is `1`.
|
||||
====
|
||||
|
||||
NOTE: Optimistic Locking is only supported with single-entity operations and not for batch operations.
|
||||
|
||||
[[cassandra.template.query]]
|
||||
== Querying Rows
|
||||
|
||||
|
||||
@@ -427,6 +427,7 @@ Types are derived from the declaration by default.
|
||||
* `@Tuple`: Applied at the type level to use a type as a mapped tuple.
|
||||
* `@Element`: Applied at the field level to specify element or field ordinals within a mapped tuple.
|
||||
Types are derived from the property declaration by default.
|
||||
* `@Version`: Applied at field level is used for optimistic locking and checked for modification on save operations. The initial value is `zero` which is bumped automatically on every update.
|
||||
|
||||
The mapping metadata infrastructure is defined in the separate, spring-data-commons project that is both
|
||||
technology- and data store-agnostic.
|
||||
|
||||
Reference in New Issue
Block a user