我的專案中有一個服務方法,可以像這樣簡化:
@Transactional
public void myTransactionalMethod(){
try {
soSomethingAndSaveOnDB(); // private method
}catch (Exception exception){
saveSomethingOnDBWhenAnErrorOccurs(); // private method
throw exception;
}
}
該方法是事務性的,并且正在執行一些可能導致拋出例外的主要邏輯。如果出現這種情況,則必須將保存在 DB 中的任何資料恢復到以前的狀態。
但是我還需要在一個catch塊中處理拋出的例外,并在資料庫中寫入一些額外的資料來跟蹤錯誤。
我的實作的問題是throw exception導致事務回滾并阻止創建與錯誤跟蹤相關的資料的最終指令。
我想在這種情況下“禁用”事務回滾,以便在我的資料庫中正確記錄錯誤。
注意我正在重新拋出例外以將其傳播到控制器并將其轉換為 HTTP 錯誤。
哪個可以很好地解決這個問題,保持soSomethingAndSaveOnDB()和saveSomethingOnDBWhenAnErrorOccurs()方法private?
uj5u.com熱心網友回復:
這似乎更像是一種解決方法而不是解決方案,但目前是我按照評論中的建議找到的最佳方法。
我這樣修改了我的方法:
@Transactional(noRollbackFor = { ExceptionWrapper.class })
public void myTransactionalMethod(){
try {
soSomethingAndSaveOnDB(); // private method
}catch (Exception exception){
saveSomethingOnDBWhenAnErrorOccurs(); // private method
throw new ExceptionWrpper(exception);
}
}
然后我定義了一個這樣的類:
public class ExceptionWrapper extends RuntimeException {
private final RuntimeException wrappedThrowable;
}
最后在我的控制器中,我捕獲了新的例外型別,如下所示:
try {
myTransactionalMethod();
}catch(ExceptionWrapper ew){
throw ew.getWrappedThrowable();
}
uj5u.com熱心網友回復:
我想到了解決這個問題的幾種方法:
- 使用具有 PROPAGATION_REQUIRES_NEW 范圍的TransactionTemplate在
saveSomethingOnDBWhenAnErrorOccurs方法中以編程方式處理事務。這樣保存錯誤日志將在單獨的事務中完成。例如:
private final TransactionTemplate transactionTemplate;
private void saveSomethingOnDBWhenAnErrorOccurs(){
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.execute(status-> repository.saveErrorLog());
}
- 使用自注入或 ApplicationContext 來呼叫日志記錄方法。然而,這種方式需要
saveSomethingOnDBWhenAnErrorOccurs公開方法。例如,假設您的班級呼叫了MyService,則:
@Autowired
private SomeRepository someRepository;
@Autowired
private ApplicationContext applicationContext;
@Transactional
public void myTransactionalMethod(){
try {
soSomethingAndSaveOnDB(); // private method
}catch (Exception exception){
LoggingData loggingData = ...
applicationContext.getBean(MyService.class).saveSomethingOnDBWhenAnErrorOccurs(someRepository, loggingData); // private method
throw new ExceptionWrpper(exception);
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Document saveSomethingOnDBWhenAnErrorOccurs(SomeRepository someRepository, LoggingData loggingData) {
return someRepository.save(document);
}
- 使用額外的抽象層,例如:
┌────────────┐
│ Controller │
└──────┬─────┘
│
│
┌─────▼─────┐
│ MyService │
└─────┬─────┘
│
│ ┌────────────────────────────────────────────────────┐
│ one rror │@Transactional(propagation=Propagation.REQUIRES_NEW)│
└──────────?│ErrorLogging.saveSomethingOnDBWhenAnErrorOccurs │
└────────────────────────────────────────────────────┘
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/336586.html
上一篇:在SpringBoot中實作Pageable介面時出錯?
下一篇:Thymeaf計算出的URL值
