Ответ
Да, метод с Propagation.REQUIRES_NEW всегда запускается в новой, независимой транзакции, даже если вызывается из контекста существующей.
Механизм работы:
- При вызове метода
b()из методаa()текущая транзакцияaприостанавливается (suspended). - Создается и запускается новая транзакция для метода
b(). - После завершения
b()(коммита или отката) возобновляется выполнение исходной транзакции методаa.
Пример и последствия:
@Service
public class MyService {
@Transactional
public void methodA() {
// Транзакция A (TX-A) активна
repository.save(entityA); // Запись в TX-A
try {
methodB(); // Вызов метода с REQUIRES_NEW
} catch (Exception e) {
// Исключение из methodB() НЕ откатит TX-A, если мы его перехватили
}
// Продолжение работы в TX-A
// Исключение здесь откатит только TX-A, но не TX-B
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// Работает в НОВОЙ, независимой транзакции B (TX-B)
repository.save(entityB); // Запись в TX-B
// Если здесь выбросить RuntimeException, откатится ТОЛЬКО TX-B
}
}
Ключевые моменты:
- Независимость: Откат одной транзакции не влияет на другую.
- Приостановка транзакции: Требует дополнительных ресурсов от менеджера транзакций.
- Исключения: Неперехваченное исключение из
methodB()распространится вmethodA()и может привести к откатуTX-A. Чтобы этого избежать, обрабатывайте исключения внутриmethodB()или в месте вызова.
Типичное использование: Логирование, аудит или отправка уведомлений, которые должны быть сохранены, даже если основная бизнес-транзакция откатится.