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