springboot事务相关(druid+mybatis)

springboot事务相关

1. 开启全局事务支持

  • SpringbootApplication中 启用配置@EnableTransactionManagement, 用来支持@Transactional
  • 开启APO配置支持@EnableAspectJAutoProxy (exposeProxy = true) 用来支持aop方式的自动事务配置

其中 exposePorxy默认false, 设为true,才可使用AopContext.currentProxy()获取TreadLocal中当前类的代理实例

2. 新建测试类及接口

总结

  • spring.datasource.druid.default-auto-commit = truefalse 对事务执行无影响,可以不用配置, 事务生启的时候会将connection.autocommit=false

  • B.b1 -> A.save 事务有效

  • B.b1 -> A.a1 -> this.save 时,事务无效

    原因: a1方法中调用本地的save时,未通过proxy代理走 生效事务: a1 -> AopContext.currentProxy().save()


2.1 配置类

execution(* org.arrow.service.TestService.*(..)) save* 配置 REQUIRED 事务

2.2 业务接口相关方法

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() {
    // 不会开启事务
    saveTest2();
    // 开启事务
    proxy =  AopContext.currentProxy();
    proxy.saveTest1();
}

3.3 测试类

@Test
public void test(){
    testService.abcdAll();
}

4. mybatis中事务配置全量

关键点

  • 事务配置线 datasource -> TransactionManager(ds) -> txAdvice(txmanager) -> txAdvisor(txAdvice)
  • mybatis配置线 datasource -> sqlSessionFactoryBean(ds) -> mapperScannerConfigurer(sessionFactory)
  • rollbackFor的配置,默认为RuntimeException.class, 可以设置为Exception.class 相关代码
// 数据源
@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.*(..))";

// 事务的实现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;
}

// 切面的定义,pointcut及advice
@Bean
public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor txAdvice) {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
    return new DefaultPointcutAdvisor(pointcut, txAdvice);
}

5. mysql中事务的设置 (无用)

检查mysql中事务设置,springboot的事务与mysql默认事务策略无关

 show variables like 'autocommit';
> autocommit    ON

关闭自动事务
set autocommit = 0;
关闭全局autocommit
set @@global.autocommit=0;

猜你喜欢

转载自my.oschina.net/u/3234707/blog/1647321