В Spring: создастся ли новая транзакция, если метод с @Transactional вызывает другой @Transactional метод внутри того же сервиса?

«В Spring: создастся ли новая транзакция, если метод с @Transactional вызывает другой @Transactional метод внутри того же сервиса?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, новая транзакция не создастся по умолчанию. Внутренний вызов будет выполняться в рамках существующей транзакции внешнего метода.

Почему? Это связано с работой Spring AOP (проксирование). Когда вызов происходит внутри одного класса, он минует прокси-обертку, и механизм управления транзакциями не перехватывается. Такое поведение называется self-invocation.

Пример:

@Service
public class TransactionalService {

    @Transactional
    public void outerMethod() {
        // Начинается транзакция Tx1
        innerMethod(); // Этот вызов НЕ приведет к созданию новой транзакции.
        // Вся работа выполняется в Tx1
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerMethod() {
        // Несмотря на аннотацию, этот код выполнится в контексте Tx1,
        // а НЕ в новой независимой транзакции.
    }
}

Как заставить это работать?

  1. Вынести innerMethod() в отдельный бин и инжектить его.
  2. Получить ссылку на собственный прокси через AopContext.currentProxy() (требует активации exposeProxy).
  3. Использовать программируемое управление транзакциями (TransactionTemplate).