The maven coordinates of the Spring Transaction specification are as follows:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>...</version> </dependency>
This package provides the spring transaction specification and the default jta (java transaction api) implementation (under the org.springframework.transaction.jta
package), the specific implementation depends on different components, such as provided by spring-jdbc Implemented database transactions.
The core interface of Spring Transaction is transaction manager TransactionManager
, but this interface is an identification interface, and the identification implementation class is a traditional or Reactive transaction manager. Traditional and Reactive transaction managers correspond to PlatformTransactionManager
and ReactiveTransactionManager
respectively. This article only focuses on traditional transaction managers.
spring-tx provides an abstract implementation of AbstractPlatformTransactionManager
for the traditional transaction manager PlatformTransactionManager
. Generally, custom transaction managers recommend inheriting the AbstractPlatformTransactionManager
, such as spring -jdbc’s DataSourceTransactionManager
inherits this abstract class. The uml class diagram of the spring-tx transaction manager is as follows:
For official specifications on spring transactions, please refer to: Spring Transaction Management
PlatformTransactionManager
Let’s take a look at the annotations for this interface:
central interface in Spring’s imperative transaction infrastructure. Typically, applications will work with either
TransactionTemplate
or declarative transaction demarcation through AOP. It is recommended to derive from the providedorg. springframework.transaction.support.AbstractPlatformTransactionManager
class, which pre-implements the defined propagation behavior and takes care of transaction synchronization handling.
public interface PlatformTransactionManager extends TransactionManager {<!-- --> // According to the specified transaction propagation method, it is decided to return the running transaction or create a new transaction TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; \t // Commit the transaction according to TransactionStatus, if the transaction is marked as rollback-only, perform a rollback // If the current transaction is a nested inner transaction, the current commit will be ignored according to the transaction propagation method void commit(TransactionStatus status) throws TransactionException; \t // implement rollback // If the current transaction is not a new transaction (that is, a nested transaction), you only need to set the rollback-only attribute of the outer transaction according to different transaction propagation methods. // Do not call rollback on a transaction if commit throw an exception. void rollback(TransactionStatus status) throws TransactionException; }
TransactionStatus
represents the status of the current transaction execution. If it is a declarative transaction, the transaction status information is stored in ThreadLocal
, see TransactionAspectSupport
, and the current transaction status can be obtained through the static method TransactionAspectSupport#currentTransactionStatus
.
AbstractPlatformTransactionManager
Abstract base class that implements Spring’s standard transaction workflow
This abstract class provides the following workflow processing:
- Determine whether there is a transaction
- Applied Transaction Propagation Method
- Suspend or resume transactions
- Check the rollback-only flag when submitting
- Make appropriate changes to the rollback (rollback directly? Or set the rollback-only flag)
- Call the transaction synchronizer callback method (if the synchronizer is enabled)
About the transaction synchronizer: Transaction synchronization is a generic mechanism for registering callbacks that get invoked at transaction completion time. This is mainly used internally by the data access support classes for JDBC, Hibernate, JPA, etc when running within a JTA transaction: They register resources that are opened within the transaction for closing at transaction completion time, allowing e.g. for reuse of the same Hibernate Session within the transaction. The same mechanism can also be leveraged for custom synchronization needs in an application.
The transaction synchronizer is equivalent to a transaction extension point. In the final stage of the transaction, the method of the transaction synchronizer is provided to facilitate the expansion. TheTransactionSynchronization
interface provides four callback methods #beforeCommit #beforeCompletion #afterCommit #afterCompletion
The transaction synchronizer is managed by
TransactionSynchronizationManager
, allTransactionSynchronization
and Resources (such as DataSource’s Connection resource, Mybatis’ SqlSession resource) are placed inThreadLocal
, you can register, obtain resource information andTransactionSynchronization
through the static method ofTransactionSynchronizationManager
To inherit this class, the following abstract methods must be overridden:
doGetTransaction
doBegin
doCommit
doRollback
Other methods do not force rewriting, optional doSuspend, doResume, doSuspendSynchronization, doResumeSynchronization, doRollbackOnCommitException, doSetRollbackOnly, doCleanupAfterCompletion
Programmatic TransactionTemplate
TransactionTemplate
provides us with a programmatic transaction template. When we need to call a programmatic transaction, we only need to call TransactionTemplate#execute
or the interface defaultTransactionOperations#executeWithoutResult
, corresponding to the cases with and without return values, respectively. Both types of methods will finally call the TransactionTemplate#execute
method.
Use Cases:
@Service class TransactionService{<!-- --> // register somewhere @Resource private TransactionTemplate transactionTemplate; @Resource private OneMapper oneMapper; @Resource private TwoMapper twoMapper; public void runSelfDefineTransaction(){<!-- --> \t\t transactionTemplate.setIsolationLevel(TransactionDefinition.PROPAGATION_REQUIRED); transactionTemplate.setTimeout(5); transactionTemplate.setReadOnly(false); \t transactionTemplate.executeWithoutResult( transactionStatus -> {<!-- --> oneMapper. insert(...); twoMapper. insert(...); } ); } }
The source code of TransactionTemplate
is as follows:
// Inherited from TransactionDefinition, configuration can be modified public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {<!-- --> @Nullable private PlatformTransactionManager transactionManager; ... // The transaction execution process is converted into TransactionCallback incoming @Override @Nullable public <T> T execute(TransactionCallback<T> action) throws TransactionException {<!-- --> ... TransactionStatus status = this.transactionManager.getTransaction(this); T result; try {<!-- --> // Execute custom transaction operations result = action.doInTransaction(status); } catch (RuntimeException | Error ex) {<!-- --> // Transactional code throw application exception -> rollback rollbackOnException(status, ex); throw ex; } catch (Throwable ex) {<!-- --> // Transactional code threw unexpected exception -> rollback rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } \t\t\t// submit this.transactionManager.commit(status); return result; }
Declarative transaction
Spring declarative transactions are implemented through AOP, and interceptors are added to methods annotated with @Transactional
(pay attention to the usage method, otherwise it will not take effect, such as methods must be public and avoid intra-class calls), in the interceptor Call the related methods of TransactionManager
, see TransactionInterceptor
.
About AOP, you can refer to Spring AOP and proxy class execution order
Since the interceptor of the transaction does not implement the Ordered
interface, the annotation @Order
, and the annotation @Priority
, the default is the lowest priority
Declarative transactions can obtain the currently running transaction through the TransanctionAspectSupport
tool class