1. 程式人生 > 其它 >【Spring 從0開始】JdbcTemplate 資料庫事務引數

【Spring 從0開始】JdbcTemplate 資料庫事務引數

@Transactional() 註解裡有不少引數,其中我們常用到的如下:

一、propagation

表示事務傳播行為。就是說多個事務方法之間進行呼叫,這個過程中事務是如何進行管理的。

這裡的事務方法就是指對資料庫表資料進行變化操作的方法。

舉例:

有個 update() 方法:

public void update() {

}

還有個 add() 方法:

public void add() {
  // 呼叫了update()方法
  update()
}

那麼,現在當其中一個方法加上了事務註解 @Transactional 後,呼叫執行過程是怎樣的?或者說兩個都加了事務註解,又該如何?

為了解決問題,spring 事務傳播行為有 7 種:

  • REQUIRED:預設引數。如果有事務在執行,當前方法就在這個事務內執行,否則就開啟一個新的事務,並在自己的事務內執行。
  • REQUIRES_NEW:當前的方法必須在啟動新事務,並在它自己的事務內執行,如果有事務在進行,應該將它掛起。
  • SUPPORTS:如果有事務在執行,當前的方法就在這個事務內執行,否則它可以不執行在事務中。
  • NOT_SUPPORTED:當前的方法不應該執行在事務中,如果有執行的事務,將它掛起。
  • MANDATORY:當前的方法必須執行在事務內部,如果沒有正在執行的事務,就丟擲異常。
  • NEVER:當前的方法不應該在事務中執行,如果有執行的事務,就丟擲異常。
  • NESTED:如果有事務在執行,當前的方法就應該在這個事務的巢狀事務內執行,否則,就啟動一個新的事務,並在自己的事務內執行。

1. REQUIRED

如果有事務在執行,當前方法就在這個事務內執行,否則就開啟一個新的事務,並在自己的事務內執行。


@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
  methodB();
  // do something
}
 
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
  // do something
}
  • 當呼叫 methodA 時,因為當前上下文不存在事務,所以會開啟一個新的事務。當執行到 methodB 時,發現當前上下文存在事務,因此就加入到當前事務來執行。
  • 當單獨呼叫 methodB 時,因為當前上下文不存在事務,所以會開啟一個新的事務。

2. REQUIRES_NEW

當前的方法必須在啟動新事務,並在它自己的事務內執行,如果有事務在進行,應該將它掛起。


@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
doSomeThingA();
methodB();
doSomeThingB();
// do something else
}
 
 
// 事務屬性為REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // do something
}

當呼叫 methodA 時,開啟了 事務 A。執行到 methodB 時,開啟一個事務B,此時事務 A 掛起,當事務 B 執行完成後,繼續執行事務 A 。

  • 這裡的事務 A 稱為外層事務。
  • 這裡的事務 B 則稱為內層事務。

3. SUPPORTS

如果有事務在執行,當前的方法就在這個事務內執行,否則它可以不執行在事務中。


@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
 methodB();
// do something
}
 
// 事務屬性為SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
public void methodB() {
    // do something
}
  • 當呼叫 methodA 時,methodB 加入到 methodA 的事務中,事務的執行。
  • 當單獨的呼叫 methodB 時,methodB方法是非事務的執行的。

4. NOT_SUPPORTED

當前的方法不應該執行在事務中,如果有執行的事務,將它掛起。

  • 當呼叫 methodA 時,開啟 事務 A。當執行到 methodB 時,掛起事務A,以非事務的方式執行 methodB 。
  • 當單獨的呼叫 methodB 時,methodB方法是非事務的執行的。

5. MANDATORY

當前的方法必須執行在事務內部,如果沒有正在執行的事務,就丟擲異常。

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
 methodB();
// do something
}
 
// 事務屬性為MANDATORY
@Transactional(propagation = Propagation.MANDATORY)
public void methodB() {
    // do something
}
  • 當呼叫 methodA 時,methodB 則加入到 methodA 的事務中,事務地執行。
  • 當單獨呼叫 methodB 時,因為當前沒有一個活動的事務,則會丟擲異常。

6. NEVER

當前的方法不應該在事務中執行,如果有執行的事務,就丟擲異常。

7. NESTED

如果有事務在執行,當前的方法就應該在這個事務的巢狀事務內執行,否則,就啟動一個新的事務,並在自己的事務內執行。

  • 當單獨執行 methodB ,開啟事務 B,執行。
  • 當執行 methodA 時,開啟事務 A,執行到 methodB,開啟內層事務 B。

注意 當執行 methodA 時,這裡是一個巢狀事務。

如果外層事務失敗,則會回滾內層事務所做的操作。但是內層事務的失敗不會引起外層事務的回滾

二、ioslation

設定事務隔離級別。

因為不同的事務隔離級別會引起不同的問題,比如:髒讀、不可重複讀、幻讀。

相關的內容在之前有過介紹,有興趣的可以自行跳轉過去:【Mysql】資料庫事務,髒讀、幻讀、不可重複讀

所以要解決,需要設定對應的隔離級別:

  • READ_UNCOMMITTED: 讀未提交
  • READ_COMMITTED: 讀已提交
  • REPEATABLE_READ: 可重複讀
  • SERIALIZABLE: 序列化

三、timeout

設定超時時間。

事務需要在一定時間內進行提交,如果沒提交,就回滾。

預設值是 -1 ,表示不超時。如果設定時間,單位是秒(s)。

四、readOnly

設定是否只讀。

預設值 false,表示可以查詢,也可以進行新增、修改、刪除操作。

當設定為 true,只可以進行查詢操作。

五、rollbackFor

設定出現哪些異常後就進行事務的回滾。

六、noRollbackFor

設定出現哪些異常後,不進行事務的回滾。

--不要用肉體的勤奮,去掩蓋思考的懶惰--