Spring事務回滾的兩種方法

語言: CN / TW / HK

theme: Chinese-red

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第30天,點選檢視活動詳情


當然,Spring事務回滾的前提是你當前使用的資料庫必須支援事務,比如MySQL的Innodb是支援的,但Mysaim則是不支援事務的。

方法一

  1. 使用 @Transaction 來配置自動回滾,可以配置在類上,也可以配置在方法上(作用域不同),但對final或private修飾的方法無效,且該類必須是受spring所管控的,也就是被已經被注入的類,而不是new出來的類。

    • 若配置在方法上,則該方法被加上了事務
    • 若配置在類上,則等於給該類的所有方法都加上了該註解。此時如果在該類下的某個方法也加了 @Transaction ,則該方法使用自己的配置,其他方法使用類上的配置。

java @Service @Transactional public class UserServiceImpl implements UserService { @Override public void save(User user) { //some code //db operation } }

  1. 若被配置的方法或類丟擲了異常,則事務會被自動回滾,除非你在該方法中手動捕獲了異常,且沒有丟擲新的異常。

    可以使用 @Transactional(rollbackFor = Exception.class) 來設定針對特定的異常進行事務回滾,如果不設定則預設會回滾 RuntimeException and Error (參考自原始碼內文件)。

    ```java @Service @Transactional(rollbackFor = Exception.class) public class UserServiceImpl implements UserService { @Resource private UserMapper userMapper;

    @Override
    public void save(User user) {
        userMapper.insert(user);
        throw new RuntimeException(); // 丟擲異常,事務回滾,上面的insert插入失敗。
    }
    

    } ```

方法二

通過注入 DataSourceTransactionManager 來手動開啟事務,手動回滾事務,用於丟擲異常被catch後,進行手動回滾,可控程度更高,可以更靈活的使用。

  1. 先注入 DataSourceTransactionManager 事務管理物件
  2. new 一個 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 物件
  3. 使用 TransactionStatus status = transactionManager.getTransaction(def);來開啟一個事務,
  4. 使用 transactionManager.rollback(status); 來回滾這個事務
  5. 使用 transactionManager.commit(status); 來提交這個事務

```java @Service public class UserServiceImpl implements UserService { @Autowired private DataSourceTransactionManager transactionManager;

@Override @Transactional public void save(User user) { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // explicitly setting the transaction name is something that can only be done programmatically def.setName("SomeTxName"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

   TransactionStatus status = transactionManager.getTransaction(def);
   try {
       // execute your business logic here
       //db operation
   } catch (Exception ex) {
       transactionManager.rollback(status);
       throw ex;
   }

} } // 此程式碼案例來自Alibaba Coding Guidelines ```