Spring 引导:具有两个数据库的事务,如果第二个数据库失败,则回滚第一个数据库

Spring Boot: Transaction with two DB, rollback first DB if second DB fails

我正在构建一个 Spring 具有两个数据源的启动应用程序。我需要在 DB1 中进行更新,然后在 DB2 中进行更新。但是如果 DB2 的更新失败,DB1 更新应该回滚。

我看到 a post 遇到了同样的问题,但是 ChainedTransactionManager 实现对我不起作用。

我当前的实现是:

我有 2 个具有不同数据源的 bean 用于事务管理器:

    <bean id="dataSourceTransactionManagerSP" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" primary="true">
        <constructor-arg ref="dataSourceSP"/>
    </bean>

    <bean id="dataSourceTransactionManagerBOL" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSourceBOL"/>
    </bean>

我有两种进行更新的交易方法。由于某些奇怪的原因,@Transactional 注释在任何方法中都不起作用。但是到目前为止,这两种方法在它的数据源中运行良好。

对于第一个数据库:

    @Override
    public Boolean updateDB1() {
        transactionTemplate.setTransactionManager(dataSourceTransactionManagerSP);
        return transactionTemplate.execute(status -> {
            boolean r1 = repository1.update1();
            boolean r2 = repository1.update2();
            return r1 && r2;
        });
    }

对于第二个数据库:

    @Override
    public Boolean updateDB2() {
        transactionTemplate.setTransactionManager(dataSourceTransactionManagerBOL);
        return transactionTemplate.execute(status -> {
            boolean r1 = repository2.update1();
            boolean r2 = repository2.update2();
            return r1 && r2;
        });
    }

但现在我需要一个调用 updateDB1updateDB2 的方法,如果 DB2 失败,DB1 回滚。

    @Override
    public Boolean updateBoth() {

        return transactionTemplate.execute(status -> {
            boolean r1 = updateDB1();
            boolean r2 = updateDB2();
            return r1 && r2;
        });
    }

我知道这行不通,因为我需要指定 TransactionManager,但这就是问题所在,我有两个事务管理器。

我认为你应该在同一个方法updateBoth 中控制回滚DB1。在 spring 文档中你可以找到这个例子:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

  protected void doInTransactionWithoutResult(TransactionStatus status) {
    try {
      updateOperation1();this is your updateDB1()
      updateOperation2();-->this is your updateDB2()
    } catch (SomeBusinessExeption ex) {
      status.setRollbackOnly();
    }
  }
});

我会让 updateDB2() 启动一些可以在 catch 中捕获的自定义异常,然后使状态回滚。在这种情况下,假设您要手动回滚的是 DB1,则要使用的事务管理器是 dataSourceTransactionManagerSP (DB1)。你可以通过 @Transactional("dataSourceTransactionManagerBOL")

来控制 DB2 的事务