1. 程式人生 > 實用技巧 >Spring的事務傳播機制(通俗易懂)

Spring的事務傳播機制(通俗易懂)

概述

Spring的事務傳播機制有7種,在列舉Propagation中有定義。

1.REQUIRED

PROPAGATION_REQUIRED:如果當前沒有事務,就建立一個新事務,如果當前存在事務,就加入該事務,該設定是最常用的預設設定。

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

@Transactional

(propagation= Propagation.REQUIRED)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

呼叫methdoA,如果methodB發生異常,觸發事務回滾,也會methodA中的也會回滾。

2.SUPPORTS

PROPAGATION_SUPPORTS:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。

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

@Transactional(propagation= Propagation.SUPPORTS)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果呼叫methodA,再呼叫methodB,MehtodB會加入到MethodA的開啟的當前事務中。

如果直接呼叫methodB,當前沒有事務,就以非事務執行。

3.MANDATORY

PROPAGATION_MANDATORY:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就丟擲異常。

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

@Transactional(propagation= Propagation.MANDATORY)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果呼叫methodA,再呼叫methodB,MehtodB會加入到MethodA的開啟的當前事務中。

如果直接呼叫methodB,當前沒有事務,就會丟擲異常。

4.REQUIRES_NEW

PROPAGATION_REQUIRES_NEW:建立新事務,無論當前存不存在事務,都建立新事務。

@Transactional(propagation= Propagation.REQUIRED)
public void methodA(){
    // do something pre
	methodB();
    // do something post
}

@Transactional(propagation= Propagation.REQUIRES_NEW)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

呼叫methodA,會先開啟事務1,執行A的something pre的程式碼。再呼叫methodB,methdoB會開啟一個事務2,再執行自身的程式碼。最後在執行methodA的something post。如果method發生異常回滾,只是methodB中的程式碼回滾,不影響methodA中的程式碼。如果methodA發生異常回滾,只回滾methodA中的程式碼,不影響methodB中的程式碼。

簡言之,不會影響別人,也不會被別人影響。

5.NOT_SUPPORTED

PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

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

@Transactional(propagation= Propagation.NOT_SUPPORTED)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

呼叫methodA,再呼叫methodB,methodA開啟的事務會被掛起,即在methodB中不齊作用,相當於沒有事務,methodB內部丟擲異常不會回滾。methodA內的程式碼發生異常會回滾。

直接呼叫methodB,不會開啟事務。

6.NEVER

PROPAGATION_NEVER:以非事務方式執行操作,如果當前存在事務,則丟擲異常。

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

@Transactional(propagation= Propagation.NEVER)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

7. NESTED

PROPAGATION_NESTED:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則按REQUIRED屬性執行。

@Transactional(propagation= Propagation.REQUIRED)
public void methodA(){
    // do something pre
	methodB();
    // do something post
}

@Transactional(propagation= Propagation.NESTED)
public void methodB(){
// do something
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

呼叫methodA,開啟一個事務,執行something pre的程式碼,設定回滾點savepoint,再呼叫methodB的程式碼,如果methodB裡丟擲異常,此時回滾到之前的saveponint。再然後執行methodA裡的something post的程式碼,最後提交或者回滾事務。
巢狀事務,外層的事務如果回滾,會導致內層的事務也回滾;但是內層的事務如果回滾,僅僅是回滾自己的程式碼,不影響外層的事務的程式碼。