我有一个方法可以对一些与文件系统和数据库交互的服务进行多次调用。问题是我实际上不知道如何正确实现错误处理,以防中途出错。好吧,就我而言,Spring 会使用 @Transactional
恢复所有数据库更改。注解。但是文件系统呢?
目前我想到的一切都是这样的:
public void myMethod() throws MyMethodException{
try {
doFirstThingWithDatabase();
doSecondThingWithDatabase();
doFirstThingWithFileSystem();
doSecondThingWithFileSystem();
} catch(FirstDatabaseThingException e) {
logger.error(e.getMessage());
throw new MyMethodException(e);
} catch(SecondThingWithDatabaseException(e) {
logger.error(e.getMessage());
revertFirstDatabaseChange();
throw new MyMethodException(e);
} catch(FirstFSThingException e) {
logger.error(e.getMessage());
revertFirstDatabaseChange();
revertSecondDatabaseChange(); //and what if first reversion is impossible and also throws an exception?
throw new MyMethodException(e);
} catch(SecondFSThingException e) {
logger.error(e.getMessage);
revertFirstDatabaseChange();
revertSecondDatabaseChange();
revertFirstFSChange();
throw new MyMethodException(e);
}
}
但对我来说似乎很难看,因为我重复了一些代码。这种情况的最佳做法是什么?
最佳答案
您可以使用 Spring 事件和事件监听器。
在DB服务中,在执行可能抛出DB异常的语句之前,
发布一个允许 TransactionalEventListener
的事件如果出现事务回滚,则执行特定的回滚处理。
这可能看起来像:
@Transactional
public void doFirstThingWithDatabase(Foo foo) {
applicationEventPublisher.publishEvent(new FooInsertionEvent(foo));
fooRepo.save(foo);
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void rollBackFooInsertion(FooInsertionEvent fooInsertionEvent) {
String info = fooInsertionEvent.getAnyRequiredInfo();
// use that info to make the DB in the correct state
}
这样,与该数据库异常相关的自定义逻辑回滚将在没有任何捕获的情况下执行。对第二个数据库异常情况应用相同的想法。
最后你的代码看起来像:
public void myMethod() throws MyMethodException{
try {
doFirstThingWithDatabase(); // processed by the listener
doSecondThingWithDatabase(); // processed by the listener
doFirstThingWithFileSystem(); // processed below when doSecondThingWithFileSystem() fails
doSecondThingWithFileSystem(); // no required
} catch(SecondFSThingException e) {
logger.error(e.getMessage);
revertFirstFSChange();
throw new MyMethodException(e);
}
catch(Exception e) {
logger.error(e.getMessage);
throw new MyMethodException(e);
}
}
关于java - 在多个资源请求的情况下恢复更改的最佳做法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61561892/