public class R2dbcTransactionManager
extends org.springframework.transaction.reactive.AbstractReactiveTransactionManager
implements org.springframework.beans.factory.InitializingBean
ReactiveTransactionManager
implementation for a single R2DBC ConnectionFactory. This class is
capable of working in any environment with any R2DBC driver, as long as the
setup uses a ConnectionFactory as its Connection factory
mechanism. Binds a R2DBC Connection from the specified
ConnectionFactory to the current subscriber context, potentially
allowing for one context-bound Connection per ConnectionFactory.
Note: The ConnectionFactory that this transaction manager
operates on needs to return independent Connections.
The Connections may come from a pool (the typical case), but the
ConnectionFactory must not return scoped scoped Connections
or the like. This transaction manager will associate Connection
with context-bound transactions itself, according to the specified propagation
behavior. It assumes that a separate, independent Connection can
be obtained even during an ongoing transaction.
Application code is required to retrieve the R2DBC Connection via
ConnectionFactoryUtils.getConnection(ConnectionFactory)
instead of a standard R2DBC-style ConnectionFactory.create() call.
Spring classes such as DatabaseClient use this strategy implicitly.
If not used in combination with this transaction manager, the
ConnectionFactoryUtils lookup strategy behaves exactly like the
native ConnectionFactory lookup; it can thus be used in a portable fashion.
Alternatively, you can allow application code to work with the standard
R2DBC lookup pattern ConnectionFactory.create(), for example for code
that is not aware of Spring at all. In that case, define a
TransactionAwareConnectionFactoryProxy for your target ConnectionFactory,
and pass that proxy ConnectionFactory to your DAOs, which will automatically
participate in Spring-managed transactions when accessing it.
This transaction manager triggers flush callbacks on registered transaction
synchronizations (if synchronization is generally active), assuming resources
operating on the underlying R2DBC Connection.
| Constructor and Description |
|---|
R2dbcTransactionManager()
Create a new
R2dbcTransactionManager instance. |
R2dbcTransactionManager(io.r2dbc.spi.ConnectionFactory connectionFactory)
Create a new
R2dbcTransactionManager instance. |
| Modifier and Type | Method and Description |
|---|---|
void |
afterPropertiesSet() |
protected Duration |
determineTimeout(org.springframework.transaction.TransactionDefinition definition)
Determine the actual timeout to use for the given definition.
|
protected reactor.core.publisher.Mono<Void> |
doBegin(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager,
Object transaction,
org.springframework.transaction.TransactionDefinition definition) |
protected reactor.core.publisher.Mono<Void> |
doCleanupAfterCompletion(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager,
Object transaction) |
protected reactor.core.publisher.Mono<Void> |
doCommit(org.springframework.transaction.reactive.TransactionSynchronizationManager TransactionSynchronizationManager,
org.springframework.transaction.reactive.GenericReactiveTransaction status) |
protected Object |
doGetTransaction(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager) |
protected reactor.core.publisher.Mono<Void> |
doResume(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager,
Object transaction,
Object suspendedResources) |
protected reactor.core.publisher.Mono<Void> |
doRollback(org.springframework.transaction.reactive.TransactionSynchronizationManager TransactionSynchronizationManager,
org.springframework.transaction.reactive.GenericReactiveTransaction status) |
protected reactor.core.publisher.Mono<Void> |
doSetRollbackOnly(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager,
org.springframework.transaction.reactive.GenericReactiveTransaction status) |
protected reactor.core.publisher.Mono<Object> |
doSuspend(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager,
Object transaction) |
io.r2dbc.spi.ConnectionFactory |
getConnectionFactory()
Return the R2DBC
ConnectionFactory that this instance manages transactions for. |
boolean |
isEnforceReadOnly()
Return whether to enforce the read-only nature of a transaction through an
explicit statement on the transactional connection.
|
protected boolean |
isExistingTransaction(Object transaction) |
protected io.r2dbc.spi.ConnectionFactory |
obtainConnectionFactory()
Obtain the
ConnectionFactory for actual use. |
protected reactor.core.publisher.Mono<Void> |
prepareTransactionalConnection(io.r2dbc.spi.Connection con,
org.springframework.transaction.TransactionDefinition definition,
Object transaction)
Prepare the transactional
Connection right after transaction begin. |
protected io.r2dbc.spi.IsolationLevel |
resolveIsolationLevel(int isolationLevel)
Resolve the isolation level constant to a R2DBC
IsolationLevel. |
void |
setConnectionFactory(io.r2dbc.spi.ConnectionFactory connectionFactory)
Set the R2DBC
ConnectionFactory that this instance should manage transactions for. |
void |
setEnforceReadOnly(boolean enforceReadOnly)
Specify whether to enforce the read-only nature of a transaction (as indicated by
TransactionDefinition.isReadOnly() through an explicit statement on the
transactional connection: "SET TRANSACTION READ ONLY" as understood by Oracle,
MySQL and Postgres. |
protected RuntimeException |
translateException(String task,
io.r2dbc.spi.R2dbcException ex)
Translate the given R2DBC commit/rollback exception to a common Spring exception to propagate
from the
AbstractReactiveTransactionManager.commit(org.springframework.transaction.ReactiveTransaction)/AbstractReactiveTransactionManager.rollback(org.springframework.transaction.ReactiveTransaction) call. |
public R2dbcTransactionManager()
R2dbcTransactionManager instance.
A ConnectionFactory has to be set to be able to use it.public R2dbcTransactionManager(io.r2dbc.spi.ConnectionFactory connectionFactory)
R2dbcTransactionManager instance.connectionFactory - the R2DBC ConnectionFactory to manage transactions forpublic void setConnectionFactory(@Nullable
io.r2dbc.spi.ConnectionFactory connectionFactory)
ConnectionFactory that this instance should manage transactions for.
This will typically be a locally defined ConnectionFactory, for example an connection pool.
The ConnectionFactory passed in here needs to return independent Connections.
The Connections may come from a pool (the typical case), but the ConnectionFactory
must not return scoped Connections or the like.
TransactionAwareConnectionFactoryProxy@Nullable public io.r2dbc.spi.ConnectionFactory getConnectionFactory()
ConnectionFactory that this instance manages transactions for.protected io.r2dbc.spi.ConnectionFactory obtainConnectionFactory()
ConnectionFactory for actual use.ConnectionFactory (never null)IllegalStateException - in case of no ConnectionFactory setpublic void setEnforceReadOnly(boolean enforceReadOnly)
TransactionDefinition.isReadOnly() through an explicit statement on the
transactional connection: "SET TRANSACTION READ ONLY" as understood by Oracle,
MySQL and Postgres.
The exact treatment, including any SQL statement executed on the connection,
can be customized through through prepareTransactionalConnection(io.r2dbc.spi.Connection, org.springframework.transaction.TransactionDefinition, java.lang.Object).
public boolean isEnforceReadOnly()
setEnforceReadOnly(boolean)public void afterPropertiesSet()
afterPropertiesSet in interface org.springframework.beans.factory.InitializingBeanprotected Object doGetTransaction(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager) throws org.springframework.transaction.TransactionException
doGetTransaction in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected boolean isExistingTransaction(Object transaction)
isExistingTransaction in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerprotected reactor.core.publisher.Mono<Void> doBegin(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager, Object transaction, org.springframework.transaction.TransactionDefinition definition) throws org.springframework.transaction.TransactionException
doBegin in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected Duration determineTimeout(org.springframework.transaction.TransactionDefinition definition)
definition - the transaction definitionTransactionDefinition.getTimeout()protected reactor.core.publisher.Mono<Object> doSuspend(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager, Object transaction) throws org.springframework.transaction.TransactionException
doSuspend in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected reactor.core.publisher.Mono<Void> doResume(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager, @Nullable Object transaction, Object suspendedResources) throws org.springframework.transaction.TransactionException
doResume in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected reactor.core.publisher.Mono<Void> doCommit(org.springframework.transaction.reactive.TransactionSynchronizationManager TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction status) throws org.springframework.transaction.TransactionException
doCommit in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected reactor.core.publisher.Mono<Void> doRollback(org.springframework.transaction.reactive.TransactionSynchronizationManager TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction status) throws org.springframework.transaction.TransactionException
doRollback in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected reactor.core.publisher.Mono<Void> doSetRollbackOnly(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction status) throws org.springframework.transaction.TransactionException
doSetRollbackOnly in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerorg.springframework.transaction.TransactionExceptionprotected reactor.core.publisher.Mono<Void> doCleanupAfterCompletion(org.springframework.transaction.reactive.TransactionSynchronizationManager synchronizationManager, Object transaction)
doCleanupAfterCompletion in class org.springframework.transaction.reactive.AbstractReactiveTransactionManagerprotected reactor.core.publisher.Mono<Void> prepareTransactionalConnection(io.r2dbc.spi.Connection con, org.springframework.transaction.TransactionDefinition definition, Object transaction)
Connection right after transaction begin.
The default implementation executes a "SET TRANSACTION READ ONLY" statement if the
"enforceReadOnly" flag is set to true and the
transaction definition indicates a read-only transaction.
The "SET TRANSACTION READ ONLY" is understood by Oracle, MySQL and Postgres and may work with other databases as well. If you'd like to adapt this treatment, override this method accordingly.
con - the transactional R2DBC Connectiondefinition - the current transaction definitiontransaction - the transaction objectsetEnforceReadOnly(boolean)@Nullable protected io.r2dbc.spi.IsolationLevel resolveIsolationLevel(int isolationLevel)
IsolationLevel. If you'd like to extend isolation level translation for vendor-specific
IsolationLevels, override this method accordingly.isolationLevel - the isolation level to translate.null if not resolvable or the isolation level
should remain default.TransactionDefinition.getIsolationLevel()protected RuntimeException translateException(String task, io.r2dbc.spi.R2dbcException ex)
AbstractReactiveTransactionManager.commit(org.springframework.transaction.ReactiveTransaction)/AbstractReactiveTransactionManager.rollback(org.springframework.transaction.ReactiveTransaction) call.task - the task description (commit or rollback).ex - the SQLException thrown from commit/rollback.