Как установить «noRollbackFor` на «табличке транзакции»?

#spring #spring-boot

Вопрос:

Учитывая, что у меня настроена табличка транзакции, как показано ниже (где я начинаю новую транзакцию в рамках существующей транзакции), как я могу предотвратить откат родительской ( @Transactional ) транзакции, когда код внутри дочерней транзакции создает определенное исключение? По сути, эмулируя noRollbackFor параметр @Transactional .

 @Transactional
public void foo() {
    bar();
}

private void bar() {
    TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager);
    transactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRES_NEW);

    transactionTemplate.execute(__ -> {
        // ...
    });
}
 

Ответ №1:

Это невозможно с таблицей транзакций.
TransactionTemplate не поддерживает правила отката.
См.: https://github.com/spring-projects/spring-framework/issues/25086

Это сделано специально: TransactionTemplate не поддерживает пользовательские правила отката. Технически TransactionTemplate даже не знает о атрибуте TransactionAttribute, поскольку этот вариант является расширенным определением, поддерживаемым только TransactionInterceptor (и, следовательно, также находящимся в пакете последнего). Шаблон работает на основе простого определения транзакций и использует фиксированное поведение отката для всех исключений, создаваемых из его обратных вызовов, эффективно устраняя ошибки и исключения времени выполнения.

В качестве альтернативы вы можете использовать PlatformTransactionManager напрямую: внедрить его, вызвать getTransaction на нем, выполнить некоторые операции с ресурсами, затем вызвать фиксацию в блоке finally… и обрабатывать потенциальные исключения во время выполнения любым необходимым способом, без вызова отката. Вы также можете выборочно обрабатывать результат, если в конечном итоге вызовете фиксацию (или откат, если на то пошло) для завершения транзакции.

Альтернативное решение, позволяющее лучше контролировать то, что откатывается, и то, что должно потерпеть неудачу, — это использование точек сохранения, см. https://dzone.com/articles/transaction-savepoints-in-spring-jdbc