Spring Boot transaction control

Posted by phpn00bf4life on Mon, 07 Mar 2022 20:53:14 +0100

introduction

In the process of business development and database operation, we will basically involve the operation of transactions, which can ensure the integrity of business logic. All data access technologies have transaction processing mechanisms. These technologies provide API s to start transactions, commit transactions to complete data operations, or roll back data in case of errors. Spring's transaction mechanism uses a unified mechanism to handle transactions of different data access technologies. Spring's transaction mechanism provides a PlatformTransactionManager interface. Transactions of different data access technologies are implemented with different interfaces.

Programming transaction

The programmed transaction management uses the TransactionTemplate or directly uses the underlying platform transactionmanager. For programmatic transaction management, spring recommends using the TransactionTemplate.

Data access technologyEncapsulation class
JDBCDataSourceTransactionManager
JPAJpaTransactionManager
HibernateHibernateTransactionManager
JDOJdoTransactionManager
Distributed transactionJtaTransactionManager
@Resource
TransactionTemplate transactionTemplate;

// Programming transactions using TransactionTemplate
    @Override
    public void sendMessage(Integer usId, String content) {
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        transactionTemplate.execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try {
                    Message message = new Message();
                    for (int i = 0; i < 5; i++) {
                        if(i == 3){
                            throw new RuntimeException();
                        }
                        message.setContent(content);
                        message.setUsId(usId);
                        messageMapper.insert(message);
                    }
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                    e.printStackTrace();
                }
                return null;
            }
        });
    }
@Resource
private DataSourceTransactionManager transactionManager;

// Programming transactions using transactionTemplate
    @Override
    public void sendMessage(Integer usId, String content) {
        //Define transaction isolation level, propagation behavior,
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        //The transaction status class is obtained according to the transaction definition through the getTransaction method of PlatformTransactionManager;
        //After obtaining the transaction status, Spring decides how to start the transaction according to the propagation behavior
        TransactionStatus status = transactionManager.getTransaction(def);
        List<User> list = userMapper.selectAll();
        int i = list.size();
        System.out.println("Total number of records in the table:"+i);
        try {
            User user = new User();
            user.setName("test_test");
            userMapper.addUser(user);
            transactionManager.commit(status);  //Commit transactions bound in status
        } catch (RuntimeException e) {
            transactionManager.rollback(status);  //RollBACK 
        }
        i = userMapper.selectAll().size();
        System.out.println("Total number of records in the table:"+i);
    }

Declarative transaction

Programming transactions should be implemented separately each time, but when the business volume is large and the function is complex, using programming transactions is undoubtedly painful. Unlike declarative transactions, declarative transactions are non intrusive and will not affect the implementation of business logic.

Declarative transaction management is implemented by AOP. Its essence is to intercept before and after the execution of the target method. Add or create a transaction before the execution of the target method. After the execution of the method, choose to commit or rollback the transaction according to the actual situation.

@Transactional annotation configuration transaction management

Description of common parameters

Parameter nameFunction description
readOnlyThis attribute is used to set whether the current transaction is read-only. If it is set to true, it means read-only, false means read-write, and the default value is false. For example: @ Transactional(readOnly=true)
rollbackForThis property is used to set the array of exception classes that need to be rolled back@ Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassNameThis property is used to set the array of exception class names that need to be rolled back@ Transactional(rollbackForClassName={“RuntimeException”,”Exception”})
noRollbackForThis property is used to set the array of exception classes that do not need to be rolled back@ Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassNameThis property is used to set the array of exception class names that do not need to be rolled back@ Transactional(noRollbackForClassName={“RuntimeException”,”Exception”})
propagationThis property is used to set the propagation behavior of the transaction. For example: @ Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
isolationThis attribute is used to set the transaction isolation level of the underlying database. The transaction isolation level is used to deal with the concurrency of multiple transactions. Generally, the default isolation level of the database can be used
timeoutThis attribute is used to set the timeout seconds of transactions. The default value is - 1, which means never timeout

Transaction propagation behavior

  • REQUIRED: if a transaction currently exists, join the transaction; If there is no current transaction, a new transaction is created.
  • SUPPORTS: if a transaction currently exists, join the transaction; If there are currently no transactions, continue to run in a non transactional manner.
  • MANDATORY: if a transaction currently exists, join the transaction; If there is no current transaction, an exception is thrown.
  • REQUIRES_NEW: create a new transaction. If there is a current transaction, suspend the current transaction.
  • NOT_SUPPORTED: run in non transaction mode. If there is a transaction, suspend the current transaction.
  • NEVER: runs in a non transactional manner. If there is a transaction, an exception will be thrown.
  • NESTED: if a transaction currently exists, create a transaction to run as a NESTED transaction of the current transaction; If there is no transaction at present, this value is equivalent to REQUIRED

@Implementation principle of Transactional annotation

When using @ Transactional annotation to annotate a target method, Spring will use AOP proxy to generate a proxy object, which will decide whether to use TransactionInterceptor interceptor to intercept according to the attribute configuration information of @ Transactional annotation. If the method needs to use transaction control, it needs to use the TransactionInterceptor transaction interceptor to intercept the method, create and start the transaction before the execution of the target method, and then execute the target method. Finally, after the execution of the target method, according to whether there are exceptions, Use the abstract transaction manager AbstractPlatformTransactionManager to operate the data source. The data source commits or rolls back the transaction.

matters needing attention

  • @Transactional only works on public methods

  • In one @ Transactional method in the same class, if another @ Transactional method is removed, the transaction of the second method will be invalid and ignored by Spring AOP.

  • After trying to catch the exception of the method, the thing will fail. Transaction needs to be rolled back manually

// The exception capture transaction is invalid and needs to be rolled back manually
    @Transactional(rollbackFor = Exception.class)
    public void test1() {
        try{
            // Business logic
        }catch(Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        }
    }
  • Transactions can also be rolled back based on the rollback point

//Set rollback point
Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint(); 
// Business logic
    
//Rollback to savePoint
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);

summary

This article mainly introduces some operations of spring boot on transactions, hoping to be useful to you~~

 

Reference article:

https://blog.csdn.net/qq_32867467/article/details/82944473

https://blog.csdn.net/acmman/article/details/82926410

 

Topics: Java Database Spring