Spring事务-教你如何在一个事务中开启另外一个事务

目录

开场

简单的例子:

Spring事务几种传播机制:

Spring事务回滚策略:

Spring事务失效的几个原因:


开场

Spring项目,需要在一个事务中开启另一个事务。

上面提到的情景可能不常见,但是还是会有的,一旦遇到,如果业务比较复杂,就会很麻烦,但是还是有解决的方案的,比如将一个service方法拆成两个方法,也就是将两个操作的事务分开。

但是这只适用于业务比较简单的,如果出现多次数据库的写操作,而我们调用的系统只需要其中一个写操作的最新数据,如果我们将它分开,那么如果调用目标系统出现异常的时候,那么之前的写操作就不能回滚了。

简单的例子:

@Service
public class ServiceA {

    @Transactional
    public void doSomething(){

        向数据库中添加数据;

        调用其他系统;
    }
}

这里就用伪代码来做示例了,当我们执行了“向数据库中添加数据”,我们去数据库中查询,发现并没有我们添加的数据

但是当我们的service这个方法执行完成之后,数据库中就有这条数据了,这是由于数据库的隔离性造成的。

spring中的事务注解@transactional提供了一个参数:

Propagation propagation() default Propagation.REQUIRED;

这个参数是定义spring事务的传递性的,默认值为required,也就是如果有事务,就加入事务,如果没有,就创建事务。

这个参数的值有很多,例如REQUIRES_NEW,这个值就代表创建一个新的事务,与原来的事务分开。这个好像能解决我们的问题。

我们将刚刚那个方法修改一下:

@Service
public class ServiceA {

    @Transactional
    public void doSomething(){

        insert();

        调用其他系统;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void insert(){
        向数据库中添加数据;
    }
}

执行之后,发现结果还是没有改变,必须要整体执行完成,数据库中数据才会出现,说明还是在一个事务中。

我们再将代码修改一下:

@Service
public class ServiceA {

    @Autowired
    private ServiceB serviceB;
    @Transactional
    public void doSomething(){

        serviceB.insert();

        调用其他系统;
    }
}

@Service
public class ServiceB {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void insert(){
        向数据库中添加数据;
    }
}

我们将要事务分离出来的方法写在另一个service中,再次测试,发现执行完插入语句之后,数据库中就已经能查到数据了,说明事务分离了,完成了我们的需求。

当然spring其实也考虑这个,在spring的配置中,我们只需要添加标签

 图片

或者

 图片

并且在代码的调用中要求使用代理对象去调用即可:

图片

Spring事务几种传播机制:

  1. PROPAGATION_REQUIRED:默认的Spring事物传播级别,若当前存在事务,则加入该事务,若不存在事务,则新建一个事务。
  2. PAOPAGATION_REQUIRE_NEW:若当前没有事务,则新建一个事务。若当前存在事务,则新建一个事务,新老事务相互独立。外部事务抛出异常回滚不会影响内部事务的正常提交。
  3. PROPAGATION_NESTED:如果当前存在事务,则嵌套在当前事务中执行。如果当前没有事务,则新建一个事务,类似于REQUIRE_NEW
  4. PROPAGATION_SUPPORTS:支持当前事务,若当前不存在事务,以非事务的方式执行。
  5. PROPAGATION_NOT_SUPPORTED:以非事务的方式执行,若当前存在事务,则把当前事务挂起。
  6. PROPAGATION_MANDATORY:强制事务执行,若当前不存在事务,则抛出异常.
  7. PROPAGATION_NEVER:以非事务的方式执行,如果当前存在事务,则抛出异常。

Spring事务回滚策略:

  1. 默认只有在抛出运行时异常时才会回滚
  2. 可以配置@Transactional(rollbackFor = Exception.class),来指定异常类型回滚。

Spring事务失效的几个原因:

  1. 没有被Spring管理
  2. 方法不是public
  3. 自身调用导致事务失效
  4. 数据源没有配置事务管理器
  5. 配置不支持事务,@Transactional(propagation = Propagation.NOT_SUPPORTED)
  6. 异常被吃掉了,导致失败后没有回滚
  7. 异常类型配置错误或者格式配置错误
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值