Skip to content

Latest commit

 

History

History
86 lines (72 loc) · 2.94 KB

r2dbc-transactions.adoc

File metadata and controls

86 lines (72 loc) · 2.94 KB

Transactions

A common pattern when using relational databases is grouping multiple queries within a unit of work that is guarded by a transaction. Relational databases typically associate a transaction with a single transport connection. Consequently, using different connections results in using different transactions. Spring Data R2DBC includes transaction-awareness in DatabaseClient that lets you group multiple statements within the same transaction by using {spring-framework-ref}/data-access.html#transaction[Spring’s Transaction Management]. Spring Data R2DBC provides an implementation for ReactiveTransactionManager with R2dbcTransactionManager.

The following example shows how to programmatically manage a transaction

Example 1. Programmatic Transaction Management
ReactiveTransactionManager tm = new R2dbcTransactionManager(connectionFactory);
TransactionalOperator operator = TransactionalOperator.create(tm); (1)

DatabaseClient client = DatabaseClient.create(connectionFactory);

Mono<Void> atomicOperation = client.execute("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
  .bind("id", "joe")
  .bind("name", "Joe")
  .bind("age", 34)
  .fetch().rowsUpdated()
  .then(client.execute("INSERT INTO contacts (id, name) VALUES(:id, :name)")
    .bind("id", "joe")
    .bind("name", "Joe")
    .fetch().rowsUpdated())
  .then()
  .as(operator::transactional); (2)
});
  1. Associate the TransactionalOperator with the ReactiveTransactionManager.

  2. Bind the operation to the TransactionalOperator.

{spring-framework-ref}/data-access.html#transaction-declarative[Spring’s declarative Transaction Management] is a less invasive, annotation-based approach to transaction demarcation, as the following example shows:

Example 2. Declarative Transaction Management
@Configuration
@EnableTransactionManagement                                                           (1)
class Config extends AbstractR2dbcConfiguration {

  @Override
  public ConnectionFactory connectionFactory() {
    return // ...
  }

  @Bean
  ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) { (2)
    return new R2dbcTransactionManager(connectionFactory);
  }
}

@Service
class MyService {

  private final DatabaseClient client;

  MyService(DatabaseClient client) {
    this.client = client;
  }

  @Transactional
  public Mono<Void> insertPerson() {

    return client.execute("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
      .bind("id", "joe")
      .bind("name", "Joe")
      .bind("age", 34)
      .fetch().rowsUpdated()
      .then(client.execute("INSERT INTO contacts (id, name) VALUES(:id, :name)")
        .bind("id", "joe")
        .bind("name", "Joe")
        .fetch().rowsUpdated())
      .then();
  }
}
  1. Enable declarative transaction management.

  2. Provide a ReactiveTransactionManager implementation to back reactive transaction features.