2020年4月26日 星期日

使用交易的傳播機制

@Transactional的屬性propagation定義了交易的邊界(boundary)或稱為傳播的方式。因為@Transactional標註的方法可能再呼叫其他方法,Spring會呼叫TransactionManagergetTransaction()方法來取得或建立與資料庫的交易,並根據屬性propagation的設定決定要啟動和暫停交易;但並非TransactionManager的所有實作都直接支援所有交易傳播方式。後續介紹幾種常用的傳播方式以及它們如何作用。
REQUIRED的機制傳播交易
Propagation.REQUIRED」是屬性propagation預設值,使用方式如下:
@Transactional (propagation = Propagation.REQUIRED)
public void requiredCase() { 
    // ... 
}
因為是預設,也可以省略:
@Transactional
public void requiredCase() { 
    // ... 
}
若方法上標註@Transactional (propagation = Propagation.REQUIRED)Spring將:
1.     檢查是否有使用中的交易,如果不存在就「建立一個新的交易」。
2.     若存在交易但驗證為無效,則拋出例外。
3.     若存在交易且驗證為有效,則使用該交易。
這樣的概念可以使用以下的偽代碼(pseudo-code)來示意:
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
return createNewTransaction();
SUPPORTS的機制傳播交易
若屬性propagation值使用「Propagation.SUPPORTS」:
@Transactional (propagation = Propagation.SUPPORTS)
public void supportsCase() { 
    // ... 
}
Spring將:
1.     檢查是否有使用中的交易,如果不存在就「不使用交易」。
2.     若存在交易但驗證為無效,則拋出例外。
3.     若存在交易且驗證為有效,則使用該交易。
這樣的概念可以使用以下的偽代碼(pseudo-code)來示意:
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
return emptyTransaction();
MANDATORY的機制傳播交易
若屬性propagation值使用「Propagation.MANDATORY」:
@Transactional(propagation = Propagation.MANDATORY)
public void mandatoryCase() { 
    // ... 
}
Spring將:
1.     檢查是否有使用中的交易,如果不存在就「拋出例外」
2.     若存在交易但驗證為無效,則拋出例外。
3.     若存在交易且驗證為有效,則使用該交易。
這樣的概念可以使用以下的偽代碼(pseudo-code)來示意:
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
throw IllegalTransactionStateException;
NEVER的機制傳播交易
若屬性propagation值使用「Propagation.NEVER」:
@Transactional(propagation = Propagation.NEVER)
public void neverCase() { 
    // ... 
}
Spring預期不存在交易;執行時期將檢查是否有使用中的交易,若存在就拋出例外
這樣的概念可以使用以下的偽代碼(pseudo-code)來示意:
if (isExistingTransaction()) {
    throw IllegalTransactionStateException;
}
return emptyTransaction;
NOT_SUPPORTED的機制傳播交易
若屬性propagation值使用「Propagation.NOT_SUPPORTED」:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void notSupportedCase() { 
    // ... 
}
Spring將檢查是否有使用中的交易,如果存在就「暫停」;因此商業邏輯將在交易暫停的情況下被執行。
使用JTATransactionManager可以直接支援這類需求,其他情況則可能是以模擬的方式進行。
REQUIRES_NEW的機制傳播交易
若屬性propagation值使用「Propagation.NEVER」:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewCase() { 
    // ... 
}
Spring將:
1.     檢查是否有使用中的交易,如果不存在就「建立新交易」
2.     若存在交易則暫停原交易,並建立新交易。
這樣的概念可以使用以下的偽代碼(pseudo-code)來示意:
if (isExistingTransaction()) {
    suspend(existing);
    try {
        return createNewTransaction();
    } catch (exception) {
        resumeAfterBeginException();
        throw exception;
    }
}
return createNewTransaction();
NOT_SUPPORTED相似,使用JTATransactionManager可以直接支援這類需求,其他情況則可能是以模擬的方式進行。

沒有留言:

張貼留言