spring boot -- Transactional事务的相关

一、传播特性

  • @Transactional(propagation=Propagation.REQUIRED) :如果外层调用方法本身有事务, 那么就加入到该事务中, 没有的话新建一个(这是默认的设置项)
  • @Transactional(propagation=Propagation.NOT_SUPPORTED) :以非事务方式运行,如果外层调用方法存在事务,则把当这个事务挂起。
  • @Transactional(propagation=Propagation.REQUIRES_NEW) :不管外层调用方法否存在事务,都创建一个自己的事务,外层调用方法的事务挂起,自己的执行完毕,再执行调用方事务
  • @Transactional(propagation=Propagation.MANDATORY) :如果外层调用方法存在事务,则加入该事务;如果外层调用方法没有事务,则抛出异常
  • @Transactional(propagation=Propagation.NEVER) :以非事务方式运行,如果外层调用方法存在事务,则抛出异常。
  • @Transactional(propagation=Propagation.SUPPORTS) :如果外层调用方法存在事务,则加入该事务;如果外层调用方法没有事务,则以非事务的方式继续运行。
  • @Transactional(propagation=Propagation.NESTED) :如果外层调用方法存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果外层调用方法没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED

二、事务失效的可能原因

2.1、访问权限

Spring的事务代理通常是通过Java动态代理或CGLIB动态代理生成的,这些代理要求目标方法是公开可访问的(public)。私有方法无法被代理,因此事务将无效。将方法改成public或protected即可(idea有报错提醒)。

2.2、目标类没有被spring管理

Spring的事务管理需要在Spring容器中配置的Bean上才能生效。如果目标类没有被spring管理,那么事务将无法被应用。

2.3、方法内部调用

事务管理是基于动态代理对象的代理逻辑实现的,那么如果在类内部调用类内部的事务方法,这个调用事务方法的过程并不是通过代理对象来调用的,而是直接通过this对象来调用方法,绕过的代理对象,肯定就是没有代理逻辑了。

@Component
public class TestService {
    @Resource
    TestMapper testMapper;
    
    @Transactional
    public void test1() {
        int re = testMapper.insert(new Test(10,20,30));
        if (re > 0) {
            throw new NeedToInterceptException("need intercept");
        }
        testMapper.insert(new Test(210,20,30));
    }
    public void test2(){
        //内部调用事务方法
        test1();
    }
}

2.4、多线程调用

事务信息是跟线程绑定的。因此在多线程环境下,事务的信息都是独立的,将会导致Spring在接管事务上出现差异。

2.4、数据库不支持事务

这种情况出现的概率并不高,事务能否生效数据库引擎是否支持事务是关键。常用的MySQL数据库默认使用支持事务的innodb引擎。一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了

2.5、传播特性错误

事务传播属性定义了事务如何传播到嵌套方法或外部方法。如果事务传播属性设置不正确,可能会导致事务失效或不符合预期的行为,以下是传播特性

  • @Transactional(propagation=Propagation.REQUIRED) :如果外层调用方法本身有事务, 那么就加入到该事务中, 没有的话新建一个(这是默认的设置项)
  • @Transactional(propagation=Propagation.NOT_SUPPORTED) :以非事务方式运行,如果外层调用方法存在事务,则把当这个事务挂起。
  • @Transactional(propagation=Propagation.REQUIRES_NEW) :不管外层调用方法否存在事务,都创建一个自己的事务,外层调用方法的事务挂起,自己的执行完毕,再执行调用方事务
  • @Transactional(propagation=Propagation.MANDATORY) :如果外层调用方法存在事务,则加入该事务;如果外层调用方法没有事务,则抛出异常
  • @Transactional(propagation=Propagation.NEVER) :以非事务方式运行,如果外层调用方法存在事务,则抛出异常。
  • @Transactional(propagation=Propagation.SUPPORTS) :如果外层调用方法存在事务,则加入该事务;如果外层调用方法没有事务,则以非事务的方式继续运行。
  • @Transactional(propagation=Propagation.NESTED) :如果外层调用方法存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果外层调用方法没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED

2.6、自己捕获异常

在代码中手动try…catch了异常

2.7、final或者static修饰

spring事务的源码,事务底层使用了aop,也就是通过jdk动态代理或者cglib,生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。

2.8、未开启事务

sspringboot通过DataSourceTransactionManagerAutoConfiguration类,已经默认开启了事务。
传统的spring项目,则需要在applicationContext.xml文件中,手动配置事务相关参数。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值