Вопрос проверяет понимание границ транзакций и их поведения при внешних вызовах в Spring.
REST-вызов уже будет выполнен и не может быть отменён. Spring-транзакции управляют только операциями с базой данных. Когда последняя операция с БД падает, транзакция откатывается, отменяя первую операцию с БД, но REST-вызов остаётся выполненным. Это может привести к несогласованности данных.
Транзакции в Spring управляют только ресурсами, поддерживающими транзакционность (например, БД), но не внешними вызовами.
Поведение в описанном сценарии:
Границы транзакции:
Транзакция начинается перед первой операцией с БД
Охватывает только операции с транзакционными ресурсами
Внешние вызовы (REST, messaging) находятся вне контроля транзакции
Последовательность событий:
@Transactional
public void process() {
// 1. Операция с БД - выполняется в транзакции
userRepository.save(user);
// 2. REST-вызов - выполняется ВНЕ транзакции
restTemplate.postForObject("http://api.com/notify", data, String.class);
// 3. Ещё одна операция с БД - в транзакции
orderRepository.save(order); // ← если здесь исключение
}Что происходит при ошибке:
REST-вызов уже завершён и не может быть отменён
Транзакция откатывается, отменяя первую операцию save()
Возникает несогласованность: уведомление отправлено, но данные не сохранены
Решение проблемы:
Перепроектирование логики:
Вынести REST-вызов за пределы транзакции
Использовать паттерн "Transaction-outbox"
Применить компенсирующие транзакции
Использование Saga-паттерна:
Разбить процесс на этапы
Для каждого этапа предусмотреть компенсирующее действие
Асинхронная обработка:
Сохранить задачу на отправку в БД в той же транзакции
Отправлять REST-запросы асинхронно после коммита транзакции
Вывод: Внешние вызовы не участвуют в транзакциях, что требует особого подхода к проектированию распределённых операций.