Skip to content

Commit a0dc6f1

Browse files
committed
#418 - Document optimistic locking using @Version.
1 parent ad1e75f commit a0dc6f1

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

src/main/asciidoc/reference/r2dbc-repositories.adoc

+39
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ The following table describes the strategies that Spring Data R2DBC offers for d
317317
If the identifier property is `null`, then the entity is assumed to be new. Otherwise, it is assumed exist in the datbase.
318318
|Implementing `Persistable` |If an entity implements `Persistable`, Spring Data R2DBC delegates the new detection to the `isNew(…)` method of the entity.
319319
See the link:$$https://docs.spring.io/spring-data/data-commons/docs/current/api/index.html?org/springframework/data/domain/Persistable.html$$[Javadoc] for details.
320+
|Optimistic Locking through `@Version` | If an entity uses Optimistic Locking by (version property annotated with `@Version`), Spring Data R2DBC checks if the entity is new by inspecting the version property whether its value corresponds with Java's default initialization value. That is `0` for primitive types and `null` for wrapper types.
320321
|Implementing `EntityInformation` |You can customize the `EntityInformation` abstraction used in `SimpleR2dbcRepository` by creating a subclass of `R2dbcRepositoryFactory` and overriding `getEntityInformation(…)`.
321322
You then have to register the custom implementation of `R2dbcRepositoryFactory` as a Spring bean.
322323
Note that this should rarely be necessary. See the link:{spring-data-r2dbc-javadoc}/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactory.html[Javadoc] for details.
@@ -334,6 +335,44 @@ One important constraint is that, after saving an entity, the entity must not be
334335
Note that whether an entity is new is part of the entity's state.
335336
With auto-increment columns, this happens automatically, because the ID gets set by Spring Data with the value from the ID column.
336337

338+
[[r2dbc.optimistic-locking]]
339+
=== Optimistic Locking
340+
341+
The `@Version` annotation provides syntax similar to that of JPA in the context of R2DBC and makes sure updates are only applied to documents with a matching version.
342+
Therefore, the actual value of the version property is added to the update query in such a way that the update does not have any effect if another operation altered the document in the meantime. In that case, an `OptimisticLockingFailureException` is thrown.
343+
The following example shows these features:
344+
345+
====
346+
[source,java]
347+
----
348+
@Table
349+
class Person {
350+
351+
@Id Long id;
352+
String firstname;
353+
String lastname;
354+
@Version Long version;
355+
}
356+
357+
R2dbcEntityTemplate template = …;
358+
359+
Mono<Person> daenerys = template.insert(new Person("Daenerys")); <1>
360+
361+
Person other = template.select(Person.class)
362+
.matching(query(where("id").is(daenerys.getId())))
363+
.first().block(); <2>
364+
365+
daenerys.setLastname("Targaryen");
366+
template.save(daenerys); <3>
367+
368+
template.save(other).subscribe(); // emits OptimisticLockingFailureException <4>
369+
----
370+
<1> Initially insert row. `version` is set to `0`.
371+
<2> Load the just inserted row. `version` is still `0`.
372+
<3> Update the row with `version = 0`. Set the `lastname` and bump `version` to `1`.
373+
<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`.
374+
====
375+
337376
:projection-collection: Flux
338377
include::../{spring-data-commons-docs}/repository-projections.adoc[leveloffset=+2]
339378

0 commit comments

Comments
 (0)