#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