Spring Boot: транзакция с двумя БД, откат первой БД при сбое второй БД - PullRequest
0 голосов
/ 24 мая 2019

Я создаю приложение Spring Boot, которое имеет два источника данных. Мне нужно сделать обновление в DB1, а затем в DB2. Но если обновление DB2 завершится неудачно, обновление DB1 должно откатиться.

Я видел сообщение с той же проблемой, но реализация ChainedTransactionManager не работает для меня.

Моя текущая реализация:

У меня есть 2 компонента с разными источниками данных для менеджеров транзакций:

    <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;
        });
    }

Но теперь мне нужен метод, который вызывает updateDB1 и updateDB2, а если DB2 дает сбой, происходит откат DB1.

    @Override
    public Boolean updateBoth() {

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

Я знаю, что это не сработает, потому что мне нужно указать TransactionManager, но это проблема, у меня есть два менеджера транзакций.

1 Ответ

1 голос
/ 24 мая 2019

Я думаю, что вы должны сделать контроль отката DB1 в том же методе updateBoth.Весной 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).Вы можете управлять Транзакцией DB2 с помощью @Transactional ("dataSourceTransactionManagerBOL")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...