Spring transactions and transaction propagation mechanism

Table of Contents

1: Implementation of transactions in Spring

2: Spring transaction operation

2.1: Spring programmatic implementation of transactions

2.1.1:User table

2.1.2: Methods declared by the Mapper interface

2.1.3:Service layer

2.1.4:Controller layer

2.2: Spring declarative transactions (automatic)

2.2.1: Implementation case

2.2.2: @Transactional Notes

Three: Transaction isolation level

3.1: Atomicity

3.2: Consistency

3.3: Persistence

3.4: Isolation

3.4.1: Dirty read

3.4.2: Non-repeatable reading

3.4.3: Phantom reading

3.4.4: Spring transaction isolation level

Four: Spring transaction propagation mechanism

4.1: What is the transaction propagation mechanism?

4.2: What are the transaction propagation mechanisms?

?edit


One: Implementation of transactions in Spring

Transaction operations in Spring are divided into two categories:

1: Programmatic transactions (manually write code to operate transactions)

2: Declarative transactions (use annotations to automatically open and submit transactions)

Two: Spring transaction operations

In the spring operation, it is also divided into three steps, starting the transaction, rolling back the transaction, and committing the transaction.

Below, we operate through cases.

2.1:Spring Programmatic Implementation of Transactions

2.1.1:User table

#Create user table
create table user(
    userId int primary key auto_increment,
    #The username is agreed to be unique
    username varchar(64) unique,
    #password
    passwordvarchar(64)
);

2.1.2: Methods declared by the Mapper interface

The method declared in mapper is the operation of adding user information. The number returned represents the number of rows affected.

@Mapper
public interface UserMapper {
    //return int data
    int addUserInfo(UserInfo userInfo);
}

2.1.3:Service layer

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public Integer addUserInfo(UserInfo userInfo){
        return userMapper.addUserInfo(userInfo);
    }
}

2.1.4:Controller layer

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    //Add this annotation to introduce the transaction manager
    @Autowired
    private DataSourceTransactionManager transactionManager;
    //Set transaction attributes
    @Autowired
    private TransactionDefinition transactionDefinition;
    //Return the number of affected rows
    @RequestMapping("/add")
    public Integer add(UserInfo userInfo){
        //The first step: non-null verification
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        //1. Open the transaction, get and open the transaction
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
        Integer integer = userService.addUserInfo(userInfo);
        System.out.println(integer);
        //2: Rollback transaction
        transactionManager.rollback(transaction);
        return integer;

    }

}

At this time, since we rolled back the addition of user information, the new user information cannot be added to the database, but the returned value is still 1.

But when we convert the rollback transaction into a commit transaction, we see if the added user information can be obtained in the database.

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    //Add this annotation to introduce the transaction manager
    @Autowired
    private DataSourceTransactionManager transactionManager;
    //Set transaction attributes
    @Autowired
    private TransactionDefinition transactionDefinition;
    //Return the number of affected rows
    @RequestMapping("/add")
    public Integer add(UserInfo userInfo){
        //The first step: non-null verification
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        //1. Open the transaction, get and open the transaction
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
        Integer integer = userService.addUserInfo(userInfo);
        System.out.println(integer);
        //2: Rollback transaction
        transactionManager.commit(transaction);
        return integer;

    }

}

operation result:

2.2: Spring declarative transaction (automatic)

Add the @Transactional annotation to the controller layer to enable transactions.

Features:

1: The @Transaction annotation can be added to classes and methods. Adding it to a class means that the public methods in this class have transactions. Adding it to a method means that the method here has a transaction.

2: @Transactional, start the transaction before the method is executed, and commit the transaction after the method is executed. If an exception occurs during the method execution, the transaction will be rolled back.

2.2.1: Implementation Case

 @Transactional
    @RequestMapping("/insert")
    public Integer insert(UserInfo userInfo){
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        Integer integer = userService.addUserInfo(userInfo);
        return integer;
    }

In the above code, if no exception occurs during the method running, the transaction will be automatically submitted. What if we add an arithmetic exception to this method?

 @Transactional
    @RequestMapping("/insert")
    public Integer insert(UserInfo userInfo){
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        Integer integer = userService.addUserInfo(userInfo);
        System.out.println(integer);
        //Make an arithmetic exception
        int num=10/0;
        return integer;
    }

At this time, an arithmetic exception will be reported. If an arithmetic exception occurs in the method, then at this time, the transaction will be rolled back, that is, no new user information will be added.

2.2.2: @Transactional Notes

When there is a try-catch statement in the program, the transaction will not be rolled back even if there is an exception in the program.

 @Transactional
    @RequestMapping("/insert")
    public Integer insert(UserInfo userInfo){
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        Integer integer = userService.addUserInfo(userInfo);
        System.out.println(integer);
        //Make an arithmetic exception
        try {
            int num=10/0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return integer;
    }

When an arithmetic exception occurs in the program, we add the user name wangwu and password 12345.

Console code:

Database Table:

Judging from the above results, it is found that it has been added. At this time, the transaction has not been rolled back.

How to solve it?

Solution 1: Continue to throw exceptions and hand them over to spring

Solution 2:

 @Transactional
    @RequestMapping("/insert")
    public Integer insert(UserInfo userInfo){
        if(userInfo==null||!StringUtils.hasLength(userInfo.getUsername())
        ||!StringUtils.hasLength(userInfo.getPassword())){
            return 0;
        }
        Integer integer = userService.addUserInfo(userInfo);
        System.out.println(integer);
        //Make an arithmetic exception
        try {
            int num=10/0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            //Use code to manually roll back the transaction
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return integer;
    }

Three: Transaction Isolation Level

3.1:Atomicity

Multiple operations are packaged into a whole, and either all of them execute correctly or none of them execute.

3.2:Consistency

The data can be matched before and after the transaction.

3.3:Persistence

Various operations performed by transactions are persistently stored on the hard disk. (Once the transaction is executed successfully, all operations here are written on the hard disk)

3.4:Isolation

When executing transactions concurrently, isolation will make a trade-off between execution efficiency and data reliability. (“Isolation” describes the mutual impact between transactions executed at the same time. The higher the isolation, the lower the concurrency, and the more reliable the data)

If these two transactions modify the same table, there will be trouble at this time.

Due to possible differences in the above execution order, the execution results may be different.

3.4.1:Dirty Read

Dirty data is temporary, not final data.

How to solve dirty reads?

3.4.2: Non-repeatable read

In the same read transaction, there may be read operations involved. Multiple read operations may result in different data being read.

How to solve non-repeatable reads?

3.4.3:Phantom reading

During multiple reads of a transaction, although the data values read are the same, the result sets are different.

eg: The first time the records were read, there were 10 records, and the second time the records were read, there were 11 records. The first ten records are the same, but there is one more.

How to solve phantom reading?

3.4.4:Spring transaction isolation level

Isolation.DEFAULT: Based on the transaction isolation level of the connected database.

Four: Spring transaction propagation mechanism

4.1:What is the transaction propagation mechanism?

Spring transaction propagation mechanism defines how transactions are transmitted when multiple methods containing transactions are called to each other.

When three methods use the same mode, if there is a problem with any method, the transaction will be rolled back.

The three methods use three different modes, and the methods between each have no influence.

4.2: What are the transaction propagation mechanisms?