Реактивные транзакции следуют тому же шаблону, что и императивные:
- Транзакция запускается перед выполнением любых команд пользовательского пространства
- Запуск команд пользовательского пространства
- Фиксация (или откат)
Здесь следует отметить несколько аспектов: Соединение всегда связано с материализацией реактивной последовательности.То, что мы знаем из Thread
-связанного соединения, связанного с выполнением в императивном программировании, преобразуется в материализацию в реактивном программировании.
Таким образом, каждое (одновременное) выполнение получает назначенное соединение.
Spring Data R2DBC не поддерживает точки сохранения.Взгляните на следующий пример кода, который иллюстрирует решение о коммите или откате:
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
TransactionalOperator transactionalOperator = TransactionalOperator
.create(new R2dbcTransactionManager(connectionFactory));
transactionalOperator.execute(tx -> {
Mono<Void> insert = databaseClient.execute("INSERT INTO legoset VALUES(…)")
.then();
Mono<Long> select = databaseClient.execute("SELECT COUNT(*) FROM legoset")
.as(Long.class)
.fetch()
.first();
return insert.then(select.handle((count, sink) -> {
if(count > 10) {
tx.setRollbackOnly();
}
}));
}).as(StepVerifier::create).verifyComplete();
Здесь можно выделить следующие важные моменты:
- Мы используем
TransactionalOperator
вместо@Transactional
. - Код в
.handle()
вызывает setRollbackOnly()
для отката транзакции.
Используя @Transactional
, вы обычно используете исключения, чтобы сигнализировать об условии отката.