2020年4月26日 星期日

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

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

沒有留言:

張貼留言