Ответ
Поведение зависит от атрибута propagation транзакции внутреннего метода. Spring управляет транзакциями через AOP-прокси, поэтому вызовы должны идти через этот прокси.
Ключевые сценарии распространения (Propagation):
| Propagation | Поведение внутреннего метода |
|---|---|
REQUIRED (по умолчанию) |
Присоединяется к существующей транзакции внешнего метода. Откат во внешнем методе приведет к откату всей работы, включая внутренний метод. |
REQUIRES_NEW |
Приостанавливает текущую транзакцию и создает новую, независимую. Откат новой транзакции не затронет внешнюю, и наоборот. |
NESTED |
Создает вложенную транзакцию (точка сохранения/savepoint) внутри внешней. Откат вложенной транзакции не приводит к откату внешней. |
NOT_SUPPORTED |
Приостанавливает текущую транзакцию и выполняется без транзакции. |
NEVER |
Выбросит исключение, если вызван внутри существующей транзакции. |
Пример с REQUIRES_NEW:
@Service
public class MyService {
@Transactional
public void outerMethod() {
// Работа в транзакции Tx1
innerMethod(); // Будет выполнена в НОВОЙ транзакции Tx2
// Продолжение работы в Tx1. Откат Tx1 не откатит Tx2.
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerMethod() {
// Независимая работа в транзакции Tx2
}
}
Критически важное ограничение (Self-Invocation):
Если метод outerMethod вызывает innerMethod напрямую через this.innerMethod(), вызов минует Spring-прокси, и аннотации @Transactional внутреннего метода игнорируются. Для корректной работы вызов должен идти через прокси, например, из другого бина или через внедренную самоссылку (@Autowired).