springboot中用@Transational控制事务的注意事项

事务是javaEE开发中一个很重要的概念,他控制了对多表操作的一组事务同时成功或同时失败。关于事务的一些概念与应用,相信已经很清楚了,这里不对事务做过多的介绍,谈一谈关于springboot中事务的使用的一些注意事项。
一、springboot配置事务的方式
简单的来说,springboot中配置事务可以通过@Transational注解的方式和配之类的方式进行全局性的事务配置。都是通过动态代理实现的,被代理前后执行的方式也相同,只是前者是springboot自带的切点拦截,后者自定义的切点拦截
1.@Transational配置事务
这种方法,只需要在你需要事务的位置上方法(或类)上加@Transational注解,并配置相应的属性,包括传播行为,隔离级别,回滚异常等(没有要求用默认的也行)。
2.全局性的事务配置

@Aspect
@Configuration
public class TransactionAdviceConfig {
     

	//配置切面
    private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.xxx.service.*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

	//注入拦截器
    @Bean
    public TransactionInterceptor txAdvice() {
     
        //配置事务的属性,支持配置多个事务
        RuleBasedTransactionAttribute tx= new RuleBasedTransactionAttribute();
        //配置异常回滚
        requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        //配置传播行为
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        /**
         * 还支持其他配置
		 * setIsolationLevel
		 * setTimeout
		 * setReadOnly
		 * setName
		 * setRollbackRules
	 	 */
        //配置涉及的事务方法,以方法命名分配事务
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.addTransactionalMethod("list*", readOnlyTx);
        source.addTransactionalMethod("count*", readOnlyTx);
        return new TransactionInterceptor(transactionManager, source);
    }

    //注入切点
    @Bean
    public Advisor txAdviceAdvisor() {
     
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

二、关于动态代理
动态代理的方式有两种,一种是jdk自带的代理方式,对接口进行代理。一种是cglib的方式,对实现类进行代理。在项目中动态代理应用的非常广泛,jdk代理方式,必须要求被代理类实现接口,且代理方法只能是接口中的方法,局限性很大(启动可能会报错,事务等注解可能失灵),一般都会使用cglib的方式进行代理。
springboot引入时会依赖这个包spring-boot-autoconfigure,这个包会使默认的使用cglib方式进行代理(会覆盖一些注解的注解的属性设置,如@EnableTransactionManagement的proxyTargetClass属性),想用jdk方式代理,可以通过application.properties中通过以下方式修改

spring.aop.proxy-target-class = false

三、事务的传播行为
事务的传播的设置错误可能会导致事务失效,锁失效(设置了当前没有事务,mybatis默认每一条sql是一条事务,会立即执行commit,导致方法没执行完,锁就已经释放了)等问题。当出现一个事务中有嵌套事务发生,需要注意传播行为的设置,否则可能会发生事故。
springboot中用@Transational控制事务的注意事项_第1张图片
三、@Transational失灵现象
1.方法修饰不是public
2.同类之中,直接调用本类方法,不是通过类.方法调用,导致方法不是通过代理对象执行,而是直接本类执行,没有进行增强
3.传播行为设置错误
4.jdk动态代理方式,方法没在接口中声明
5.回滚属性设置错误,导致不能回滚,默认是RunTimeException
6.数据库引擎不支持事务
。。。。

你可能感兴趣的:(java,mysql,spring,boot)