Spring - transaction management

Spring transaction management

Spring transactions are divided into two types: programmatic transactions and declarative transactions.

1. Programming services

Program the transaction, obtain the TransactionTemplate object, and then control the transaction submission and rollback
DAO

@Component
public interface DemoDao {
    @Insert("insert into demo values(1,2000)")
    void insert();
}

Service

@Component
public class DemoService {

    @Autowired
    DemoDao demoDao;
	
	// Get TransactionTemplate object
    @Autowired
    TransactionTemplate transactionTemplate;

    // Programming transaction
    public void inset2() throws Exception {
    	// Transaction processing
        transactionTemplate.execute(new TransactionCallback<Boolean>() {
            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                demoDao.insert();
                // You can roll back here. If you want to commit, do not write this section
                status.setRollbackOnly();
                return false;
            }
        });

    }
}

Class configured

@Configuration
@ComponentScan("cn.zl")
@MapperScan("cn.zl.dao")
@EnableTransactionManagement
@PropertySource("data.yml")
public class Config {

    // Inject data source object
    @Bean
    public DataSource dataSource(DatabaseParam databaseParam){
        PooledDataSource pooledDataSource = new PooledDataSource();
        pooledDataSource.setUsername(databaseParam.getUsername());
        pooledDataSource.setPassword(databaseParam.getPassword());
        pooledDataSource.setDriver(databaseParam.getDriver());
        pooledDataSource.setUrl(databaseParam.getUrl());
        return pooledDataSource;
    }

    // Create an sql object
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource ds) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(ds); // Configure data sources
        sqlSessionFactoryBean.setTypeAliasesPackage("cn.zl.model"); // Set entity class alias
        return sqlSessionFactoryBean;
    }

    //Configure transaction manager
    @Bean
    public DataSourceTransactionManager transactionManager(DataSource ds){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(ds);
        return transactionManager;
    }
	// Inject transaction management objects to receive transactions
    @Bean
    public TransactionTemplate transactionTemplate(DataSourceTransactionManager dataSourceTransactionManager){
        TransactionTemplate transactionTemplate = new TransactionTemplate(dataSourceTransactionManager);
        return transactionTemplate;
    }
}

test

public class Main {

    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        DemoService bean2 = applicationContext.getBean(DemoService.class);
        // deal with affairs
        bean2.inset2();
    }
}

2. Declarative transactions

Programming business mainly depends on

@Component
public class DemoService {

    @Autowired
    DemoDao demoDao;
    @Transactional(rollbackFor = Exception.class)
    public void inset() throws Exception {
        demoDao.insert();
        // Exceptions thrown here can be rolled back
        throw new Exception();
    }
}

3. Take a look at the @ Transactional annotation

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

	@AliasFor("transactionManager")
	String value() default "";
	
	// These two values have the same effect. Set the manager for the transaction
	
	@AliasFor("value")
	String transactionManager() default "";

	// Set propagation behavior of transactions
	Propagation propagation() default Propagation.REQUIRED;

	// Set the isolation level of the transaction
	Isolation isolation() default Isolation.DEFAULT;

	// Set the timeout for the transaction.
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	// Set the current transaction as read-only.
	boolean readOnly() default false;

	// This attribute is used to set the array of exception classes that need to be rolled back. When the method throws an exception in the specified exception array, the transaction is rolled back.
	Class<? extends Throwable>[] rollbackFor() default {};

	// This attribute is used to set the array of exception class names that need to be rolled back. When an exception in the array of specified exception names is thrown in the method, the transaction is rolled back
	String[] rollbackForClassName() default {};

	// This attribute is used to set the array of exception names that do not need to be rolled back. When an exception in the specified exception array is thrown in the method, transaction rollback will not be performed. 
	Class<? extends Throwable>[] noRollbackFor() default {};

	// This attribute is used to set the exception class name array that does not need to be rolled back. When an exception in the specified exception name array is thrown in the method, transaction rollback will not be performed 
	String[] noRollbackForClassName() default {};

}

4. Communication of affairs

Suppose method A calls method B now, and the transaction of method A will affect method B. So this is the propagation behavior of transactions. There are four situations.

  • Method A has transactions, and method B also has transactions
  • Method A has no transactions and method B has transactions
  • Method A has transactions and method B has no transactions
  • Method A has no transactions, and method B has no transactions

4.1 PROPAGATION_REQUIRED default

When A calls B, if method A has A transaction, B will join the transaction of method A for execution. If method A has no transaction, method B starts A new transaction.

If we call method a and method B separately, a transaction will be created. If the method B is called in the method A, the method B is added to the method A.

4.2 PROPAGATION_SUPPORTS

It supports external transactions and does not create transactions by itself. If there is external, it is supported and does not run in a non transactional manner.

Simply calling method B will not create A transaction and will be executed in A non transaction manner. Here, method A must be REQUIRED. When method A calls method B, method B supports the current transaction.

4.3 PROPAGATION_MANDATORY

Mandatory external transactions. If the external transaction already exists, it is supported. If not, an exception will be thrown.


If method B is called directly from outside, an exception illegaltransactionstateexception will be thrown: no existing transaction found for transaction marked with promotion 'mandatory'. The method B is called in the method A, and the method B supports the transaction of the method A.

4.4 PROPAGATION_REQUIRES_NEW (request a new transaction)

Using PROPAGATION_REQUIRES_NEW, you need to use JTA transaction manager as the transaction manager
It does not support external transactions. If there is no external transaction, start a transaction. If there is an external transaction, suspend it.
When methodB is called separately, a transaction will be started. When methodA calls methodB, it will suspend the transaction of methodA and open a new transaction for methodB. Of course, method B transaction commit has nothing to do with rolling back the transaction with method a. The two transactions are irrelevant.

4.5 PROPAGATION_NOT_SUPPORTED (not supported)

It does not support any transaction. It will not create a transaction itself. It is always executed in a non transactional manner, and any transaction will be suspended.

When methodB is called externally, methodB will not create any transactions and run in a non transactional manner. When methodA calls methodB, the transaction of methodA will be suspended, and methodB will still run in a non transactional manner.

4.6 PROPAGATION_NEVER (never use transactions)

Never use transactions. Throw exceptions if there are external transactions.

4.7 PROPAGATION_NESTED

If an active transaction exists, a sub transaction will be opened and nested in an external transaction. If there is no active transaction, it will be executed according to the REQUIRED attribute.
JDBC version 3.0 is required

A nested transaction is a sub transaction, not a new transaction. The commit and rollback of external transactions will affect the commit and rollback of sub transactions.

Keywords: Spring

Added by lightkeepr on Wed, 19 Jan 2022 06:51:05 +0200