2020年4月26日 星期日

使用標註類別@Transactional進行交易

標註類別@org.springframework.transaction.annotation.Transactional用來將方法內的資料庫存取包含於資料庫交易中,可以設定交易的傳播(propagation),隔離(isolation),超時(timeout),唯讀(read-only)和回復(rollback)條件等,也可以設定交易管理器(transaction manager)
@Transactional的運行方式
假設我們以@Transactional標註callMethod()方法,Spring會在方法周圍(around)AOP機制處理交易需求:
createTransactionIfNecessary();  //若必要將產生交易
try {
    callMethod();
    commitTransactionAfterReturning();  //若正常結束則commit
} catch (exception) {
    rollbackTransactionAfterThrowing();  //若異常結束則rollback
    throw exception;
}
如何使用@Transactional
我們可以將@Transactional標註在介面(interfaces)、類別(classes)的宣告上,或是直接標註在方法(method)上。若彼此間衝突或不一致時,將以覆寫(override)的概念決定有效順位,原則是:
1.            標註在「類別方法」時高於「父類別方法」,又高於「介面方法」。
2.            標註在「類別宣告」時高於「父類別宣告」,又高於「介面宣告」。
3.            標註在「方法」時高於「類別宣告」或「介面宣告」。
@Transactional標註在類別的宣告上時,效果將自動擴充到類別內每一個沒有使用@Transactional標註的public方法;若privateprotected的方法上被開發者以@Transactional標註,也將自動被Spring框架忽略。
以下示範標註在介面宣告上:
@Transactional
public interface TransferService {
    void transfer(String user1, String user2, double val);
}
一般而言,不會建議在介面上直接使用類似@Transactional的功能性標註類別,因為介面的設計要考慮一般性,不見得每個實作都有需要使用資料庫交易;但如@Repository這種分類型標註類別就比較沒有這樣的限制,因為每個實作都還會是Repository類別。
一旦有介面或父類別被標註@Transactional,就可以在子類別上標註@Transactional以覆寫設定:
@Service
@Transactional
public class TransferServiceImpl implements TransferService {
    @Override
    public void transfer(String user1, String user2, double val) {
        // ...
    }
}
所以也可以在方法上直接標註@Transactional來覆寫類別上的標註:
@Transactional
public void transfer(String user1, String user2, double val) {
    // ...
}

沒有留言:

張貼留言