springboot transaction related
1. Enable global transaction support
- Enable @ EnableTransactionManagement in SpringbootApplication to support @Transactional
- Enable APO configuration support @ EnableAspectJAutoProxy (exposeProxy = true) to support automatic transaction configuration in aop mode
Where exposePorxy defaults to false and is set to true, then AopContext.currentProxy() can be used to get the proxy instance of the current class in TreadLocal
2. New test class and interface
summary
-
spring.datasource.druid.default-auto-commit = true or false has no effect on transaction execution. Configuration is not required. connection.autocommit=false will be set when transaction is generated
-
B. B1 - > a.save transaction is valid
-
B. Invalid transaction when B1 - > a.a1 - > this.save
Cause: when the local save was invoked in the a1 method, it did not go through the proxy proxy. Effective transaction: A1 - > aopcontext. Currentproxy(). Save()
2.1 configuration
execution(* org.arrow.service.TestService.*(..))
save* To configure REQUIRED affair
2.2 business interface related methods
public void saveTest1() { for (int i = 0; i < 3; i++) { Test1 test1 = new Test1(); test1.setSeq("test1_" + i); test1Mapper.insertSelective(test1); } } public void saveTest2() { for (int i = 0; i < 2; i++) { Test2 test2 = new Test2(); test2.setSeq("test2_" + i); test2Mapper.insertSelective(test2); } } public void abcdAll() { // Transaction will not be opened saveTest2(); // Open transaction proxy = AopContext.currentProxy(); proxy.saveTest1(); }
3.3 test
@Test public void test(){ testService.abcdAll(); }
4. Total transaction configuration in mybatis
Key points
- Transaction configuration line datasource -> TransactionManager(ds) -> txAdvice(txmanager) -> txAdvisor(txAdvice)
- mybatis configuration line datasource -> sqlSessionFactoryBean(ds) -> mapperScannerConfigurer(sessionFactory)
- The configuration of rollbackFor is RuntimeException.class by default, which can be set to Exception.class Related code
// data source @Bean(name = "dataSource") @ConfigurationProperties("spring.datasource.druid") public DataSource dataSource(){ return DruidDataSourceBuilder.create().build(); } @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml")); sqlSessionFactoryBean.setTypeAliasesPackage("org.arrow.shop.bean"); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mybatis/mapper/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer cfg = new MapperScannerConfigurer(); cfg.setBasePackage("org.arrow.*.dao"); cfg.setSqlSessionFactoryBeanName("sqlSessionFactory"); return cfg; } @Bean("txManager") public PlatformTransactionManager annotationDrivenTransactionManager(@Qualifier("dataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } private static final int TX_METHOD_TIMEOUT = 50000; private static final String AOP_POINTCUT_EXPRESSION = "execution(* org.arrow.shop.service.TestService.*(..))"; // Implementation of transaction Advice @Bean public TransactionInterceptor txAdvice(@Qualifier("txManager")PlatformTransactionManager m) { NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute(); readOnlyTx.setReadOnly(true); readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(); requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class))); requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); requiredTx.setTimeout(TX_METHOD_TIMEOUT); Map<String, TransactionAttribute> txMap = new HashMap<>(); txMap.put("add*", requiredTx); txMap.put("save*", requiredTx); txMap.put("insert*", requiredTx); txMap.put("update*", requiredTx); txMap.put("delete*", requiredTx); txMap.put("get*", readOnlyTx); txMap.put("query*", readOnlyTx); source.setNameMap(txMap); TransactionInterceptor txAdvice = new TransactionInterceptor(m, source); return txAdvice; } // Definition of section, pointcut and advice @Bean public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor txAdvice) { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(AOP_POINTCUT_EXPRESSION); return new DefaultPointcutAdvisor(pointcut, txAdvice); }
5. Transaction settings in MySQL (useless)
Check the transaction settings in mysql. The transaction of springboot is independent of the default transaction policy of mysql
show variables like 'autocommit'; > autocommit ON Turn off automatic transactions set autocommit = 0; Turn off global autocommit set @@global.autocommit=0;