This article has been included in Github 75K + Star’s Java project JavaGuide. JavaGuide project address: github.com/Snailclimb/… . I strongly recommend learning Java friends to see!

Hello everyone, I am Guide brother, the previous paragraph promised readers Spring transaction analysis summary finally come. This section is important, whether for a job or interview, but there are few good online references. JavaGuide Interview Shock 2.0 is here! Here comes the online version of it!

If there is any wrong or need to improve the place, please help to point out! Guide brother is very grateful!

1. What are transactions?

A transaction is a logical set of operations that either all or none of them execute.

Guide elder brother: we should all be able to carry this sentence above, below I combine our daily real development to talk about.

Each business method of our system may include multiple atomic database operations, such as the two atomic database operations in the savePerson() method below. These atomic database operations are dependent and either all or none of them are performed.

 public void savePerson(a) {
  personDao.save(person);
  personDetailDao.save(personDetail);
 }
Copy the code

In addition, it is important to note that whether transactions take effect or not is critical for the database engine to support transactions. For example, common MySQL databases use the transactional InnoDB engine by default. However, if you change the database engine to MyISAM, the application will no longer support transactions!

The most classic and often cited example of a transaction is the transfer of money. If Xiao Ming wants to transfer 1000 yuan to Xiao Hong, the transfer will involve two key operations:

  1. Reduce Xiao Ming’s balance by 1000 yuan

  2. Increase xiao Hong’s balance by 1000 yuan.

If something goes wrong between these two operations like a banking system crash or a network failure, and Ming’s balance goes down and Red’s balance doesn’t go up, that’s not right. A transaction is a guarantee that both of these critical operations will either succeed or fail.

public class OrdersService {
 private AccountDao accountDao;

 public void setOrdersDao(AccountDao accountDao) {
  this.accountDao = accountDao;
 }   @Transactional(propagation = Propagation.REQUIRED,  isolation = Isolation.DEFAULT, readOnly = false, timeout = -1)  public void accountMoney(a) {  // Small red account more than 1000  accountDao.addMoney(1000,xiaohong);  // Simulate a sudden exception, such as a sudden power outage in a bank, etc  // If transaction management is not configured, the result is that the small red account has 1000 more money and the small Ming account has no less money  int i = 10 / 0;  // Xiao Wang's account is 1000 short  accountDao.reduceMoney(1000,xiaoming);  } } Copy the code

In addition, database transactions are the basis of ACID four characteristics, the following is a brief overview.

2. What is ACID?


  • Atomicity: Transactions are the smallest unit of execution and do not allow splitting. The atomicity of the transaction ensures that the action either completes completely or does not work at all;
  • Consistency: Data is consistent before and after a transaction is executed.
  • Isolation: when accessing the database concurrently, one user’s transaction will not be disturbed by other transactions. That is, when multiple transactions are executed concurrently, the execution of one transaction should not affect the execution of other transactions.
  • Persistence: After a transaction is committed. Its changes to the data in the database are persistent and should not be affected if the database fails.

3. Go into detail about Spring’s support for transactions

Again, whether your application supports transactions depends on the database first. For example, if you use MySQL, innoDB will support transactions if you use innoDB. However, if your MySQL database uses the MyISam engine, then unfortunately, transactions are not supported at the root.

One more important point: how does MySQL guarantee atomicity?

We know that if we want to keep the atomicity of transactions, we need to roll back the operation that has been performed when an exception occurs. In MySQL, the recovery mechanism is implemented by the rollback log (undo log). All changes made in the transaction are recorded in this rollback log before the related operation is performed. If we encounter an exception during execution, we can simply use the information in the rollback log to roll back the data to where it was before the modification! Also, rollback logs are persisted to disk before data. This ensures that even in the event of a sudden database outage, when the user starts the database again, the database will be able to roll back and forth unfinished transactions through the query rollback log.

3.1. Spring supports two types of transaction management

1). Programmatic transaction management

Manual transaction management via TransactionTemplate or TransactionManager is rarely used in practice, but it will help you understand the principles of Spring transaction management.

Example code for programmatic transaction management using TransactionTemplate is as follows:

@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction(a) {

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
 @Override  protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {   try {   / /... Business code  } catch (Exception e){  / / rollback  transactionStatus.setRollbackOnly();  }   }  }); } Copy the code

Example code for programmatic transaction management using TransactionManager is as follows:

@Autowired
private PlatformTransactionManager transactionManager;

public void testTransaction(a) {

 TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());  try {  / /... Business code  transactionManager.commit(status);  } catch (Exception e) {  transactionManager.rollback(status);  } } Copy the code

2) Declarative transaction management

Recommended (least intrusive code) and actually implemented via AOP (the fully annotated approach based on @Transactional is the most used).

Example code for transaction management using the @Transactional annotation is as follows:

@Transactional(propagation=propagation.PROPAGATION_REQUIRED)
public void aMethod {
  //do something
  B b = new B();
  C c = new C();
 b.bMethod();  c.cMethod(); } Copy the code

3.2. Introduction to Spring transaction Management interface

The three most important interfaces related to transaction management in the Spring framework are as follows:

  • PlatformTransactionManager: transaction manager (platform), Spring transaction strategy core.
  • TransactionDefinition: TransactionDefinition information (transaction isolation level, propagation behavior, timeout, read only, rollback rules).
  • TransactionStatus: Transaction running status.

We can put the PlatformTransactionManager interface can be seen as business top managers, while the TransactionDefinition and TransactionStatus these two interfaces can be thought of as the description of things.

PlatformTransactionManager can according to the definition of TransactionDefinition such as transaction timeout, isolation constituency, propagation behavior, such as for transaction management, The TransactionStatus interface provides methods to obtain the status of a transaction, such as whether it is new, whether it can be rolled back, and so on.

3.2.1. PlatformTransactionManager: transaction management interface

Spring does not manage transactions directly, but provides a variety of transaction managers. The Spring transaction manager interface is: PlatformTransactionManager.

Through this interface, Spring is available for various platforms such as JDBC (DataSourceTransactionManager), Hibernate (HibernateTransactionManager), JPA (JpaTransactionManager) provides a corresponding transaction manager, But the implementation is up to each platform.

PlatformTransactionManagerThe concrete implementation of the interface is as follows:


PlatformTransactionManager interface defines three methods:

package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface PlatformTransactionManager {
 // Get transaction  TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;  // Commit the transaction  void commit(TransactionStatus var1) throws TransactionException;  // Rollback the transaction  void rollback(TransactionStatus var1) throws TransactionException; }  Copy the code

Just a second here. Why define or abstract itPlatformTransactionManagerWhat about this interface?

The main reason is to abstract out the transaction management behavior and then implement it on different platforms so that we can keep the behavior provided externally unchanged and easily extend it. I shared some time ago, “Why do we use interfaces?”

3.2.2. TransactionDefinition: Transaction attribute

The transaction manager interface PlatformTransactionManager through getTransaction (TransactionDefinition definition) method to get a transaction, The parameters in this method are the TransactionDefinition class, which defines some of the basic transaction properties.

So what are transaction attributes?

Transaction attributes can be understood as some basic configuration of a transaction, describing how transaction policies are applied to methods.

The transaction attribute contains five aspects:


There are five methods defined in the TransactionDefinition interface along with constants representing transaction properties such as isolation level, propagation behavior, and so on.

package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface TransactionDefinition {
 int PROPAGATION_REQUIRED = 0;  int PROPAGATION_SUPPORTS = 1;  int PROPAGATION_MANDATORY = 2;  int PROPAGATION_REQUIRES_NEW = 3;  int PROPAGATION_NOT_SUPPORTED = 4;  int PROPAGATION_NEVER = 5;  int PROPAGATION_NESTED = 6;  int ISOLATION_DEFAULT = -1;  int ISOLATION_READ_UNCOMMITTED = 1;  int ISOLATION_READ_COMMITTED = 2;  int ISOLATION_REPEATABLE_READ = 4;  int ISOLATION_SERIALIZABLE = 8;  int TIMEOUT_DEFAULT = -1;  // Returns the propagation behavior of the transaction. The default value is REQUIRED.  int getPropagationBehavior(a);  // Returns the isolation level of the transaction, DEFAULT  int getIsolationLevel(a);  // Returns the timeout period for the transaction. The default is -1. If the time limit is exceeded but the transaction has not completed, the transaction is automatically rolled back.  int getTimeout(a);  // Returns whether it is a read-only transaction. The default is false  boolean isReadOnly(a);   @Nullable  String getName(a); } Copy the code

3.2.3. TransactionStatus: TransactionStatus

The TransactionStatus interface is used to record the status of a transaction. This interface defines a set of methods for obtaining or determining the status of a transaction.

PlatformTransactionManager. GetTransaction (…). Method returns a TransactionStatus object.

TransactionStatus Interface The content of this interface is as follows:

public interface TransactionStatus{
    boolean isNewTransaction(a); // Is something new
    boolean hasSavepoint(a); // Whether there are recovery points
    void setRollbackOnly(a);  // Set it to rollback only
    boolean isRollbackOnly(a); // Whether to rollback only
 boolean isCompleted; // Whether it is completed } Copy the code

3.3. Transaction attribute details

In actual business development, we generally use@TransactionalAnnotation to start the transaction, many people do not know what the parameter inside this parameter means, what is used. To better use transaction management in your projects, it is highly recommended to read the following.

3.3.1. Transaction propagation behavior

Transaction propagation behavior is designed to solve the transaction problem of business layer methods calling each other.

When a transaction method is called by another transaction method, you must specify how the transaction should propagate. For example, a method may continue to run in an existing transaction, or it may start a new transaction and run in its own transaction.

Take an example!

We call the bMethod() method of class B in the aMethod () method of class A. This is when it comes to transactions between business layer methods that call each other. If our bMethod() needs to be rolled back if an exception occurs, how can we configure the transaction propagation behavior so that aMethod() rolls back as well? At this point, knowledge of transaction propagation behavior is needed, and if you don’t know it, be sure to take a look.

Class A {
    @Transactional(propagation=propagation.xxx)
    public void aMethod {
        //do something
        B b = new B();
 b.bMethod();  } }  Class B {  @Transactional(propagation=propagation.xxx)  public void bMethod {  //do something  } } Copy the code

TransactionDefinition includes the following constants that represent propagation behavior:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
 int PROPAGATION_NOT_SUPPORTED = 4;  int PROPAGATION_NEVER = 5;  int PROPAGATION_NESTED = 6; .} Copy the code

However, for ease of use, Spring defines an enumerated class: Propagation

package org.springframework.transaction.annotation;

import org.springframework.transaction.TransactionDefinition;

public enum Propagation {
  REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),   SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),   MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),   REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),   NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),   NEVER(TransactionDefinition.PROPAGATION_NEVER),   NESTED(TransactionDefinition.PROPAGATION_NESTED);    private final int value;   Propagation(int value) {  this.value = value;  }   public int value(a) {  return this.value;  }  }  Copy the code

Possible values for the correct transaction propagation behavior are as follows:

1.TransactionDefinition.PROPAGATION_REQUIRED

The most commonly used Transactional Transactional behavior is used by default with the @Transactional annotation. If a transaction exists, join the transaction. If there is no transaction currently, a new transaction is created. In other words:

  1. If the external method does not start the transaction,Propagation.REQUIREDDecorated internal methods open their own transactions independently of each other.
  2. If the external method opens the transaction and isPropagation.REQUIREDIf so, allPropagation.REQUIREDThe modified internal and external methods are part of the same transaction, and if one method is rolled back, the entire transaction is rolled back.

For example, if both aMethod() and bMethod() above use PROPAGATION_REQUIRED, they both use the same transaction, and as soon as one of the methods rolls back, the entire transaction rolls back.

Class A {
    @Transactional(propagation=propagation.PROPAGATION_REQUIRED)
    public void aMethod {
        //do something
        B b = new B();
 b.bMethod();  } }  Class B {  @Transactional(propagation=propagation.PROPAGATION_REQUIRED)  public void bMethod {  //do something  } } Copy the code

2.TransactionDefinition.PROPAGATION_REQUIRES_NEW

Creates a new transaction and suspends the current transaction if one exists. In other words, no matter whether the external method starts a transaction or not, the internal method of Propagation.REQUIRES_NEW will open a new transaction of its own, and the opened transactions are independent of each other.

For example, if our bMethod() above uses PROPAGATION_REQUIRES_NEW, aMethod still propagates PROPAGATION_REQUIRED. If aMethod() has an exception rollback, bMethod() does not follow because bMethod() starts a separate transaction. However, if bMethod() throws an exception that is not caught and the exception satisfies the transaction rollback rule,aMethod() will also roll back because the exception is detected by aMethod() ‘s transaction management mechanism.

Class A {
    @Transactional(propagation=propagation.PROPAGATION_REQUIRED)
    public void aMethod {
        //do something
        B b = new B();
 b.bMethod();  } }  Class B {  @Transactional(propagation=propagation.REQUIRES_NEW)  public void bMethod {  //do something  } } Copy the code

3.TransactionDefinition.PROPAGATION_NESTED:

If a transaction exists, a transaction is created to run as a nested transaction of the current transaction; If no current affairs, the value of equivalent to the TransactionDefinition. PROPAGATION_REQUIRED. In other words:

  1. When the external method does not start the transactionPropagation.NESTEDandPropagation.REQUIREDIn the same way, decorated internal methods open their own transactions independently of each other.
  2. If an external method starts a transaction,Propagation.NESTEDThe modified inner method belongs to a subtransaction of the external transaction. If the external main transaction is rolled back, the subtransaction is also rolled back, while the inner subtransaction can be rolled back independently without affecting the external main transaction and other subtransactions.

Here’s a quick example:

Both bMethod() and bMethod2() are rolled back if aMethod() rolls back, and bMethod() does not roll back aMethod() or bMethod().

Class A {
    @Transactional(propagation=propagation.PROPAGATION_REQUIRED)
    public void aMethod {
        //do something
        B b = new B();
 b.bMethod();  b.bMethod2();  } }  Class B {  @Transactional(propagation=propagation.PROPAGATION_NESTED)  public void bMethod {  //do something  }  @Transactional(propagation=propagation.PROPAGATION_NESTED)  public void bMethod2 {  //do something  } } Copy the code

4.TransactionDefinition.PROPAGATION_MANDATORY

If a transaction exists, join the transaction. If there is no transaction currently, an exception is thrown. (Mandatory: mandatory)

This is rarely used, so I won’t give you an example.

If the following three transaction propagation behaviors are incorrectly configured, the transaction will not be rolled back.

  • TransactionDefinition. PROPAGATION_SUPPORTS: if a transaction exists, then join the transaction; If there is no transaction currently, it continues in a non-transactional manner.
  • TransactionDefinition. PROPAGATION_NOT_SUPPORTED: run way of transaction, if a transaction exists, suspending the current transaction.
  • TransactionDefinition. PROPAGATION_NEVER: run way of transaction, if the current transaction, throw an exception.

For more information on transaction propagation behavior, see this article: “Too hard ~ The interviewer asked me to explain my understanding of Spring transaction propagation behavior using case studies.”

3.3.2 Transaction isolation level

Five constants representing the isolation level are defined in the TransactionDefinition interface:

public interface TransactionDefinition {
.    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
 int ISOLATION_REPEATABLE_READ = 4;  int ISOLATION_SERIALIZABLE = 8; .} Copy the code

As with the transaction propagation behavior section, Spring defines an enumerated class: Isolation for ease of use

public enum Isolation {

 DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

 READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
  READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),   REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),   SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);   private final int value;   Isolation(int value) {  this.value = value;  }   public int value(a) {  return this.value;  }  } Copy the code

I describe each transaction isolation level in turn:

  • TransactionDefinition.ISOLATION_DEFAULT: Uses the default isolation level of the back-end database, which MySQL uses by defaultREPEATABLE_READIsolation level used by Oracle by defaultREAD_COMMITTEDIsolation level.
  • TransactionDefinition. ISOLATION_READ_UNCOMMITTED: the lowest isolation level, use this isolation level is small, because it allows read has not yet been submitted data changes, may cause the dirty read, read or not repeatable read
  • TransactionDefinition. ISOLATION_READ_COMMITTED: allow read of concurrent transactions have to submit data, can prevent dirty reads, but phantom read or not repeatable read could still happen
  • TransactionDefinition. ISOLATION_REPEATABLE_READ: many of the same field to read the results are consistent, unless the data have been modified by itself affairs on their own, can prevent the dirty read and not repeatable read, but phantom read could still happen.
  • TransactionDefinition. ISOLATION_SERIALIZABLE: the highest isolation level, completely obey the ACID isolation level. All transactions are executed one by one so that interference between transactions is completely impossible. That is, this level prevents dirty reads, unrepeatable reads, and phantom reads. But this severely affects the performance of the program. This level is also not typically used.

Because usually use MySQL database more, here again mention a mouth!

The default isolation level supported by MySQL InnoDB storage engine is REPEATABLE-READ. We can do this by SELECT @@tx_isolation; Command to view, as follows:

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
Copy the code

Here are some things to note: Unlike the SQL standard, InnoDB storage engine uses the next-key Lock algorithm in REPEATABLE READ transaction isolation level, thus avoiding phantom reads, unlike other database systems such as SQL Server. The default isolation level of InnoDB storage engine is REPEATABLE-READ, which can guarantee the transaction isolation requirements, i.e. the SERIALIZABLE isolation level of SQL standard.

Because the lower the isolation level, the fewer locks on transaction requests, most database systems have read-committed isolation levels:, But keep in mind that InnoDB storage engine uses REPEATABLE-READ by default without any performance penalty.

For more information about transaction isolation levels, see:

  1. Understand transaction Isolation Levels with ease
  2. Interviewer: You said you were familiar with MySQL transactions? Let me ask you 10 questions

3.3.3. Transaction timeout property

A transaction timeout is the maximum time that a transaction is allowed to execute, and if the transaction has not completed after this time, the transaction is automatically rolled back. The timeout period in TransactionDefinition is represented by an int in seconds. The default value is -1.

3.3.3. Transaction read-only property

package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface TransactionDefinition {
. // Returns whether it is a read-only transaction. The default is false  boolean isReadOnly(a);  } Copy the code

For transactions that only read data queries, you can specify a transaction type of Readonly, that is, read-only transaction. Read-only transactions do not involve data modification, and the database provides some optimizations suitable for methods that have multiple database query operations.

Many people may wonder why I need transaction support for a data query operation.

Made an example MySQL innodb, according to the official website dev.mysql.com/doc/refman/… Description:

MySQL by default enables the autocommit mode for each new connection. In this mode, each SQL statement sent to the MySQL server is processed in a separate transaction, which is automatically committed and a new transaction is started at the end of execution.

However, if you annotate a method with a Transactional annotation, all SQL executed by that method is placed in a transaction. If a read-only transaction is declared, the database will optimize its execution without any additional benefit.

Without Transactional, each SQL Transactional opens a separate transaction, in which data changed by other transactions is read to the latest values in real time.

Share some answers about the transaction read-only attribute:

  1. If you execute a single query at a time, there is no need to enable transaction support. By default, the database supports read consistency during SQL execution.
  2. If you execute multiple queries, statistical query, for example, the report query, in this scenario, the multiple query SQL must ensure that the overall read consistency, otherwise, after the SQL query of the preceding article, the article after the SQL query, data changes by other users, then the total time of statistics query will be read data inconsistent state, at this time, Transaction support should be enabled

3.3.4. Transaction rollback rules

These rules define which exceptions cause the transaction to roll back and which do not. By default, a transaction is rolled back only when it encounters a run-time exception (a subclass of RuntimeException). Error also causes a transaction to roll back, but it is not rolled back when a Checked exception is encountered.


If you want to roll back a specific exception type you defined, you can do this:

@Transactional(rollbackFor= MyException.class)
Copy the code

3.4. Explain the @Transactional annotation in detail

1) @TransactionalScope of action of

  1. Methods: It is recommended to use annotations on methods, but it is important to note that this annotation can only be applied to public methods, otherwise it will not take effect.
  2. Class: If this annotation is used on a class, it applies to all public methods in that class.
  3. Interface: This parameter is not recommended for interfaces.

2) @TransactionalCommon configuration parameters of

The @Transactional annotation is available from the following source code, which includes the configuration of basic transaction attributes:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
  @AliasFor("transactionManager")  String value(a) default "";   @AliasFor("value")  String transactionManager(a) default "";   Propagation propagation(a) default Propagation.REQUIRED;   Isolation isolation(a) default Isolation.DEFAULT;   int timeout(a) default TransactionDefinition.TIMEOUT_DEFAULT;   boolean readOnly(a) default false;   Class<? extends Throwable>[] rollbackFor() default {};   String[] rollbackForClassName() default {};   Class<? extends Throwable>[] noRollbackFor() default {};   String[] noRollbackForClassName() default {};  } Copy the code

@TransactionalSummary of common configuration parameters (only list a huge amount of 5 I usually more commonly used) :

The property name instructions
propagation The propagation behavior of the transaction, with a default value of REQUIRED, the optional values described above
isolation The isolation level of the transaction is DEFAULT, the optional values described above
timeout The timeout period for a transaction. The default value is -1 (it does not timeout). If the time limit is exceeded but the transaction has not completed, the transaction is automatically rolled back.
readOnly Specifies whether the transaction is read-only. The default value is false.
rollbackFor Use to specify the type of exception that can trigger transaction rollback, and multiple exception types can be specified.

3)@TransactionalTransaction annotation principle

One question you may be asked in an interview when asking about AOP. Just a quick word!

As we know, @Transactional’s working mechanism is implemented based on AOP, which in turn uses dynamic proxies. The JDK dynamic proxy is used by default if the target object implements the interface, and CGLIB dynamic proxy is used if the target object does not implement the interface.

The createAopProxy() method determines whether to use the JDK or Cglib to create a dynamic proxy.

public class DefaultAopProxyFactory implements AopProxyFactory.Serializable {

 @Override
 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<? > targetClass = config.getTargetClass(); if (targetClass == null) {  throw new AopConfigException("TargetSource cannot determine target class: " +  "Either an interface or a target is required for proxy creation.");  }  if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {  return new JdkDynamicAopProxy(config);  }  return new ObjenesisCglibAopProxy(config);  }  else {  return new JdkDynamicAopProxy(config);  }  } .} Copy the code

When a class or a public method on that class is annotated with the @Transactional annotation, the Spring container creates a proxy class for that class at startup. When a public method with the @Transactional annotation is called, it actually calls, The invoke() method in the TransactionInterceptor class. The purpose of this method is to start the transaction before the target method, roll back the transaction if an exception occurs during the method execution, and commit the transaction after the method call completes.

The invokeWithinTransaction() method of the TransactionInterceptor class is actually called internally by the invokeWithinTransaction() method of the TransactionAspectSupport class. Since the new version of Spring overwrites this section and uses a lot of reactive programming knowledge, the source code will not be listed here.

4)Spring AOP self call problem

If another method in the same class that does not have the @Transactional annotation calls the @Transactional annotation method internally, the transaction for the @Transactional annotation method will fail.

This is due to Spring AOP proxies, because Spring transaction management takes effect only when @Transactional annotated methods are called outside of a class.

Method1 () in the MyService class calls method2(), invalidating the transaction for method2().

@Service
public class MyService {

private void method1(a) {
     method2();
 / /... } @Transactional  public void method2(a) {  / /...  } } Copy the code

The solution is to avoid self-invoking or using AspectJ instead of Spring AOP proxies in the same class.

5) @TransactionalSummary of the use of notes

  1. @TransactionalAnnotations only apply to transactions on public methods and are not recommended for use on interfaces.
  2. Avoid calls from the same class@TransactionalAnnotated methods, which invalidate transactions;
  3. Correct setup@TransactionalRollbackFor and Propagation properties, otherwise the transaction may fail to rollback
  4. .

4. Reference

  1. [summary] The @Transactional parameter in Spring transaction management :www.mobabel.net/spring transaction management…
  2. Spring the official document: docs. Spring. IO/Spring/docs…
  3. Spring5 advanced programming
  4. Get a thorough understanding of the use of @transactional in Spring: www.ibm.com/developerwo…
  5. Spring transaction propagation features: github.com/love-somnus…
  6. A: the Spring transaction propagation behavior segmentfault.com/a/119000001…
  7. A comprehensive analysis of Spring’s programmatic and declarative transaction management: www.ibm.com/developerwo…

This article is formatted using MDNICE