Spring annotation driven learning notes declarative transaction

Keywords: MySQL Spring JDBC Database

Environment building

1. Import dependent
Data source, database driver, spring JDBC module

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.44</version>
</dependency>

<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
	<groupId>c3p0</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.1.2</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>4.3.12.RELEASE</version>
</dependency>


2. Configuration data source, JdbcTemplate (a tool provided by Spring to simplify database operation) operation data
3. Mark @ Transactional on the method to indicate that the current method is a transaction method;
4. Enable transaction management enables annotation based transaction management;
       @EnableXXX
5. Configure transaction manager to control transaction;
       @Bean
       public PlatformTransactionManager transactionManager()

@EnableTransactionManagement
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {
	
	//data source
	@Bean
	public DataSource dataSource() throws Exception{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setUser("root");
		dataSource.setPassword("123456");
		dataSource.setDriverClass("com.mysql.jdbc.Driver");
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
		return dataSource;
	}
	
	//
	@Bean
	public JdbcTemplate jdbcTemplate() throws Exception{
		//Spring deals with the @ Configuration class in a special way. For methods that add components to a container, multiple calls only find components from the container
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
		return jdbcTemplate;
	}
	
	//Register transaction manager in container
	@Bean
	public PlatformTransactionManager transactionManager() throws Exception{
		return new DataSourceTransactionManager(dataSource());
	}
	

}

 

Test transaction

Add service and dao for testing

@Service
public class UserService {
	
	@Autowired
	private UserDao userDao;
	
	@Transactional
	public void insertUser(){
		userDao.insert();
		System.out.println("Insert complete...");
		int i = 10/0;
	}
}
@Repository
public class UserDao {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	public void insert(){
		String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)";
		String username = UUID.randomUUID().toString().substring(0, 5);
		jdbcTemplate.update(sql, username,19);	
	}
}

7. Test class

public class IOCTest_Tx {
	
	@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext(TxConfig.class);
	
		UserService userService = applicationContext.getBean(UserService.class);
		
		userService.insertUser();
		applicationContext.close();
	}

}

Test result: due to the error code added to the service, the inserted data is invalid and the transaction works.

 

Principle analysis

1) @ EnableTransactionManagement uses the TransactionManagementConfigurationSelector to import two components into the container:
              AutoProxyRegistrar
              ProxyTransactionManagementConfiguration
2) Autoproxyregister registers an infrastructure advisor autoproxycreator component with the container;
Infrastructure advisor autoproxycreator: using postprocessor mechanism to wrap the object after it is created and return a proxy object (enhancer). The execution method of proxy object is called by interceptor chain;


3) ProxyTransactionManagementConfiguration registers the transaction enhancer in the container;
1) the transaction enhancer uses the information of the transaction annotation, and the AnnotationTransactionAttributeSource resolves the transaction annotation
2) transaction interceptor, which stores transaction attribute information and transaction manager, is actually a method interceptor;
When the target method is executed; execution interceptor chain; transaction Interceptor:
1) get transaction related attributes first
2) get PlatformTransactionManager again. If no transactionmanager is specified in advance
Finally, a PlatformTransactionManager will be obtained from the container according to the type;
3) implementation target method
If there is an exception, get the transaction manager and use the transaction management to roll back the operation
If normal, commit the transaction using the transaction manager

Published 189 original articles, won 20 praises and 20000 visitors+
Private letter follow

Posted by bdbush on Sun, 16 Feb 2020 21:53:56 -0800