java - 在多个资源请求的情况下恢复更改的最佳做法是什么?

标签 java spring exception

我有一个方法可以对一些与文件系统和数据库交互的服务进行多次调用。问题是我实际上不知道如何正确实现错误处理,以防中途出错。好吧,就我而言,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/

相关文章:

java - Spring Security JWT 刷新 token 未过期

spring - SFTP上传文件权限被拒绝

java - 当我尝试在 net-beans 中运行它时,我收到 "java.lang.reflect.InvocationTargetException"。为什么会发生这种情况?

exception - 无法在 listenTCP 函数调用的委托(delegate)中抛出异常

java - 获取 -1 和 1 之间的随机 double 值

java - 使用 JFreeChart 在 Netbeans 中编译错误

java - 使用 JUnit 测试写入 csv 文件

java - 如何使用 Spring(和 Quartz)动态启动预定作业?

java - Spring 数据库初始化仅在应用程序重启后才有效

php - 使用 Laravel 的 TokenMismatchException : in VerifyCsrfToken. php 第 33 行