Spring Boot:与两个DB的事务,如果第二个DB失败,则回滚第一个DB

时间:2019-05-24 01:01:27

标签: java spring datasource jdbctemplate transactional

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

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

我当前的实现是:

我为事务管理器提供了两个具有不同数据源的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,但这是问题所在,我有两个事务管理器。

1 个答案:

答案 0 :(得分:1)

我认为您应该使用相同的updateBoth方法来控制回滚DB1。在春季Doc中,您可以找到以下示例:

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()启动一些自定义异常,该异常可能会被捕获,然后使状态回滚。在这种情况下,假设DB1是您要手动回滚的数据库,则要使用的事务管理器是dataSourceTransactionManagerSP(DB1)。您可以使用@Transactional(“ dataSourceTransactionManagerBOL”)控制DB2的事务