Spring事務使用有兩種方式:聲明式事務(如通過@Transactional實作注解方式或者xml配置方式)和程式設計式事務方式,優缺點如下:
- 聲明式事務:通過注解和xml配置使開發者隻關注業務開發,而不需要關注事務的送出和復原,但最小粒度在方法上,不能對一塊代碼增加事務,另外也要考慮事務嵌套帶來的副作用(比如長事務)。
- 程式設計式事務:比較靈活,需要開發者在代碼中手動的管理事務的開啟、送出、復原等操作,但若對事務了解不夠深刻,容易出錯。
這裡重點講程式設計式事務方式使用的案例和注意點,使用方式如下:
private void executeTransactional(HelpParticipationContextDTO contextDTO) {
return transactionTemplate.execute(action -> {
// 1.插入使用者資訊
int row = insertStudent();
if(row <= 0) {
throw new RuntimeException("插入失敗");
}
// 2.更新統計資訊
updateStatistics(contextDTO);
return true;
});
}
預設場景下若業務處理過程中出現RuntimeException或者Error異常就會復原,詳細參考org.springframework.transaction.support.TransactionTemplate-execute方法實作,還有一種實作方式如下:
private void executeTransactional(HelpParticipationContextDTO contextDTO) {
return transactionTemplate.execute(action -> {
try {
// 1.插入使用者資訊
int row = insertStudent();
if(row <= 0) {
throw new RuntimeException("插入失敗");
}
// 2.更新統計資訊
updateStatistics(contextDTO);
return true;
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// status.setRollbackOnly();
return false;
}
});
}
這種方式隻是把目前事務标記為復原,當事務進行送出時發現該事務已經設定了復原标記,則對目前事務進行復原,這裡要看送出事務的源代碼,如下:
// org.springframework.transaction.support.AbstractPlatformTransactionManager-commit
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 這裡就會判斷事務的復原标記
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
processCommit(defStatus);
}
總結一下,當業務出現了RuntimeException或者Error異常,Spring事務進行復原,另外程式設計式事務對代碼控制比較靈活,但是建立在對Spring事務原理了解的基礎上(上面總結了程式設計式事務使用的兩種方式)。