1. 程式人生 > 其它 >spring 事務傳播性

spring 事務傳播性

一.什麼是事務傳播性

大白話講就是,方法之間互相呼叫的時候,事務如何傳播,比如A()呼叫B(),B()的事務是和A()共用一個事務(失敗一起提交)?

還是新事務(兩者事務互不影響)?,還是說B()不需要事務?,這就是事務傳播性的意思。

    @Transactional()
    public void methodA(){
        methodB();
        //doSomething
    }

    @Transactional()
    public void methodB(){
        //doSomething
    }

程式碼中的methodB()預設的傳播性是REQUIRED,表示和methodA共用一個事務,要提交一起提交,要失敗一起回滾。

二.spring中幾種事務傳播性

事務傳播性 說明
REQUIRED 預設傳播性,如果當前有事務,就沿用當前事務,如果沒有就新建一個事務
SUPPORTS 支援當前事務,如果當前沒有事務,就以非事務執行
REQUIRES_NEW 新建一個事務,如果當前存在事務,就把當前事務掛起
NOT_SUPPORTED 不支援事務,如果當前存在事務,就把當前事務掛起。
MANDATORY 強制使用當前事務,如果當前沒有事務就拋異常
NEVER 以非事務方式執行,如果當前存在事務,則丟擲異常
NESTED 如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

三.舉例說明

1.REQUIRED

說明:支援當前事務,如果當前沒有事務就新建一個事務

insertUser()和insertStu是共用一個事務,要提交一起提交要失敗一起失敗。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
}
stuService中
@Transactional(propagation = Propagation.REQUIRED)
public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
        //這個地方發生異常,會引起insertStu也回滾,說明兩者的事務是同一個
        throw new RuntimeException();
}

2.REQUIRES_NEW

說明:開啟新的事務,如果當前存在事務,就掛起當前事務。

insertUser()的失敗回滾,不會導致insertStu的回滾,因為insertStu()在一個新的事務中。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}
//上面的方法拋異常事務的回滾,不會導致下面事務回滾,stu插入成功,user插入失敗
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);

}

3.SUPPORTS

說明:如果當前已經存在事務,那麼加入該事務,否則建立一個所謂的空事務(可以認為無事務執行)

insertUser是以非事務執行的,所以insertStu也是沒有事務的,所以兩個儲存都會成功

但是如果給inertStu加上@Transactional(propagation = Propagation.REQUIRED)insertStu是有事務的。

    public void insertUser(String name) {
        User user = new User();
        user.setName(name);
        userDao.insertUser(user);
        stuService.insertStu(name);
        throw new RuntimeException();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
    }

4.NOT_SUPPORTED

說明:不支援事務,如果當前存在事務,掛起當前事務,然後新的方法在沒有事務的環境中執行

下面的insertUser會回滾,insertStu將以非事務執行,所以不會回滾

這種的業務場景可能是,日誌寫入事務要和主事務隔離,外層事務寫入失敗,不影響日誌的寫入。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}

 @Transactional(propagation = Propagation.NOT_SUPPORTED)
 public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
 }

5.MANDATORY

說明:當前必須存在一個事務,否則丟擲異常。

因為insertUser()沒有配置事務,所以insertStu()會報錯。

異常資訊:No existing transaction found for transaction marked with propagation 'mandatory'

public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}
 @Transactional(propagation = Propagation.MANDATORY)
    public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
 }

6.NEVER

說明:不支援事務,如果當前存在事務,就丟擲異常。

因為insertUser()配置了事務,所以在insertStu中會報錯。

異常資訊:Existing transaction found for transaction marked with propagation 'never'

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    //throw new RuntimeException();
}

@Transactional(propagation = Propagation.NEVER)
public void insertStu(String name){
     Stu stu = new Stu();
     stu.setName(name);
     stuDao.insertUser(stu);
}

7.NESTED

說明:NESTED修飾的內部方法屬於外部事務的子事務,外圍主事務回滾,子事務一定回滾,而內部子事務可以單獨回滾而不影響外圍主事務和其他子事務

主要的場景可能是,下單的時候,送積分,如果下單失敗,送積分也要回滾,但送積分失敗不影響下單失敗。這種場景可以使用這種傳播性