При стандартном REQUIRED оба метода участвуют в одной транзакции. RuntimeException из doB помечает её rollback-only, даже если doA перехватил исключение.
Разбор влияния вложенных вызовов на транзакцию
При стандартном REQUIRED оба метода участвуют в одной транзакции. RuntimeException из doB помечает её rollback-only, даже если doA перехватил исключение.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Контроллер инициирует вызов метода doA() из сервиса ServiceA. Какие изменения будут зафиксированы в базе данных?
@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Transactional
public void doA() {
try {
serviceB.doB();
} catch (Exception ex) {
}
}
}
@Service
public class ServiceB {
@Transactional
public void doB() {
if (true) {
throw new IllegalStateException();
}
}
}
Ответ
При стандартном REQUIRED оба метода участвуют в одной транзакции. RuntimeException из doB помечает её rollback-only, даже если doA перехватил исключение.
При выходе из doA попытка commit приведёт к откату и обычно UnexpectedRollbackException. В показанном коде операций записи вообще нет, поэтому никакие изменения не фиксируются. Если бы записи были до ошибки, они откатились бы вместе с общей транзакцией. Результат предполагает вызовы через работающие Spring-прокси и обычные настройки rollback. REQUIRES_NEW у doB создал бы отдельную транзакцию с другим поведением, но это бизнес-решение, а не способ скрыть ошибку.