public class R2dbcTransactionManager extends AbstractReactiveTransactionManager implements 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.
AbstractReactiveTransactionManager.SuspendedResourcesHolderlogger| Constructor and Description |
|---|
R2dbcTransactionManager()
Create a new @link ConnectionFactoryTransactionManager} instance.
|
R2dbcTransactionManager(ConnectionFactory connectionFactory)
Create a new
R2dbcTransactionManager instance. |
| Modifier and Type | Method and Description |
|---|---|
void |
afterPropertiesSet() |
protected Duration |
determineTimeout(TransactionDefinition definition)
Determine the actual timeout to use for the given definition.
|
protected reactor.core.publisher.Mono<Void> |
doBegin(TransactionSynchronizationManager synchronizationManager,
Object transaction,
TransactionDefinition definition) |
protected reactor.core.publisher.Mono<Void> |
doCleanupAfterCompletion(TransactionSynchronizationManager synchronizationManager,
Object transaction) |
protected reactor.core.publisher.Mono<Void> |
doCommit(TransactionSynchronizationManager TransactionSynchronizationManager,
GenericReactiveTransaction status) |
protected Object |
doGetTransaction(TransactionSynchronizationManager synchronizationManager) |
protected reactor.core.publisher.Mono<Void> |
doResume(TransactionSynchronizationManager synchronizationManager,
Object transaction,
Object suspendedResources) |
protected reactor.core.publisher.Mono<Void> |
doRollback(TransactionSynchronizationManager TransactionSynchronizationManager,
GenericReactiveTransaction status) |
protected reactor.core.publisher.Mono<Void> |
doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
GenericReactiveTransaction status) |
protected reactor.core.publisher.Mono<Object> |
doSuspend(TransactionSynchronizationManager synchronizationManager,
Object transaction) |
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 ConnectionFactory |
obtainConnectionFactory()
Obtain the
ConnectionFactory for actual use. |
protected reactor.core.publisher.Mono<Void> |
prepareTransactionalConnection(Connection con,
TransactionDefinition definition,
Object transaction)
Prepare the transactional
Connection right after transaction begin. |
protected IsolationLevel |
resolveIsolationLevel(int isolationLevel)
Resolve the
isolation level constant to a R2DBC
IsolationLevel. |
void |
setConnectionFactory(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. |
void |
setExceptionTranslator(R2dbcExceptionTranslator exceptionTranslator)
Set the exception translator for this instance.
|
protected RuntimeException |
translateException(String task,
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. |
commit, getReactiveTransaction, prepareForCommit, registerAfterCompletionWithExistingTransaction, rollbackpublic R2dbcTransactionManager()
public R2dbcTransactionManager(ConnectionFactory connectionFactory)
R2dbcTransactionManager instance.connectionFactory - the R2DBC ConnectionFactory to manage transactions forpublic void setConnectionFactory(@Nullable 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 specified here should be the target ConnectionFactory to manage transactions
for, not a TransactionAwareConnectionFactoryProxy. Only data access code may work with
TransactionAwareConnectionFactoryProxy, while the transaction manager needs to work on the underlying target
ConnectionFactory. If there's nevertheless a TransactionAwareConnectionFactoryProxy passed in, it will be
unwrapped to extract its target ConnectionFactory.
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 Connection or the like.
TransactionAwareConnectionFactoryProxy@Nullable public ConnectionFactory getConnectionFactory()
ConnectionFactory that this instance manages transactions for.public void setExceptionTranslator(R2dbcExceptionTranslator exceptionTranslator)
If no custom translator is provided, a default R2dbcExceptionSubclassTranslator is used which translates
R2dbcException's subclasses into Springs DataAccessException hierarchy.
R2dbcExceptionSubclassTranslatorprotected 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 InitializingBeanprotected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager) throws TransactionException
doGetTransaction in class AbstractReactiveTransactionManagerTransactionExceptionprotected boolean isExistingTransaction(Object transaction)
isExistingTransaction in class AbstractReactiveTransactionManagerprotected reactor.core.publisher.Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager, Object transaction, TransactionDefinition definition) throws TransactionException
doBegin in class AbstractReactiveTransactionManagerTransactionExceptionprotected Duration determineTimeout(TransactionDefinition definition)
definition - the transaction definitionTransactionDefinition.getTimeout()protected reactor.core.publisher.Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction) throws TransactionException
doSuspend in class AbstractReactiveTransactionManagerTransactionExceptionprotected reactor.core.publisher.Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager, Object transaction, Object suspendedResources) throws TransactionException
doResume in class AbstractReactiveTransactionManagerTransactionExceptionprotected reactor.core.publisher.Mono<Void> doCommit(TransactionSynchronizationManager TransactionSynchronizationManager, GenericReactiveTransaction status) throws TransactionException
doCommit in class AbstractReactiveTransactionManagerTransactionExceptionprotected reactor.core.publisher.Mono<Void> doRollback(TransactionSynchronizationManager TransactionSynchronizationManager, GenericReactiveTransaction status) throws TransactionException
doRollback in class AbstractReactiveTransactionManagerTransactionExceptionprotected reactor.core.publisher.Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager, GenericReactiveTransaction status) throws TransactionException
doSetRollbackOnly in class AbstractReactiveTransactionManagerTransactionExceptionprotected reactor.core.publisher.Mono<Void> doCleanupAfterCompletion(TransactionSynchronizationManager synchronizationManager, Object transaction)
doCleanupAfterCompletion in class AbstractReactiveTransactionManagerprotected reactor.core.publisher.Mono<Void> prepareTransactionalConnection(Connection con, 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 IsolationLevel resolveIsolationLevel(int isolationLevel)
isolation level constant to a R2DBC
IsolationLevel. If you'd like to extend isolation level translation for vendor-specific
IsolationLevels, override this method accordingly.isolationLevel - the isolation level to translate.default.TransactionDefinition.getIsolationLevel()protected RuntimeException translateException(String task, R2dbcException ex)
AbstractReactiveTransactionManager.commit(org.springframework.transaction.ReactiveTransaction)/AbstractReactiveTransactionManager.rollback(org.springframework.transaction.ReactiveTransaction) call.
The default implementation throws a TransactionSystemException. Subclasses may specifically identify
concurrency failures etc.
task - the task description (commit or rollback).ex - the SQLException thrown from commit/rollback.DataAccessException or a
TransactionExceptionCopyright © 2018–2020 Pivotal Software, Inc.. All rights reserved.