spring事务传播机制

事务是我们开发中经常用到的,那么spring中的事务是怎么样的呢?可以用注解@Transactional注解来进行对spring事务的管理,注意:@Transactional注解只能放在public方法上面。他有一个Propagation属性,是用来控制事务的传播属性,主要有如下七个属性。

1.REQUIRED,这个是默认的属性
Support a current transaction, create a new one if none exists.

支持当前事务,如果当前没有事务,则新建事务。

如果当前存在事务,则加入当前事务,合并成一个事务。


2.MANDATORY
Support a current transaction, throw an exception if none exists.

支持当前事务,如果当前没有事务,就抛出异常。

3.NEVER
Execute non-transactionally, throw an exception if a transaction exists.
以非事务方式执行,如果当前存在事务,则抛出异常。

4.NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。  

5.REQUIRES_NEW
Create a new transaction, suspend the current transaction if one exists.
新建事务,如果当前存在事务,把当前事务挂起。


6.SUPPORTS
Support a current transaction, execute non-transactionally if none exists.
支持当前事务,如果当前没有事务,就以非事务方式执行。

7.NESTED
Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.

存在事务则运行在嵌套事务中,不存在则创建一个事务。

嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

其中比较难理解的就是NOT_SUPPORTED NESTED ,现举个例子如下:

如果ServiceA.methodA的事务级别是PROPAGATION_REQUIRED

package com.haoqiangwang.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class ServiceA {

    @Resource
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA(){
        serviceB.methodB();
    }
}

而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,

package com.haoqiangwang.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB(){

        //此时方法以非事务的状态运行
    }
}

那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。


而ServiceB.methodB的事务级别为PROPAGATION_NESTED,

package com.haoqiangwang.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {

    @Transactional(propagation = Propagation.NESTED)
    public void methodB(){

        //此时方法以新的事务的状态运行,此事务是调用它事务的子事务
    }
}

那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint,等待ServiceB.methodB的事务完成以后,他才继续执行。因为ServiceB.methodB是外部事务的子事务,那么
1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB也将回滚。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

原文地址:https://www.cnblogs.com/wanghq1994/p/12102959.html