Что произойдет при вызове @Transactional метода из не-транзакционного метода в том же классе в Spring?

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

Ответ

Транзакция не будет создана. Это происходит из-за ограничения Spring AOP: прокси-объект перехватывает только внешние вызовы, а внутренние вызовы внутри одного класса обходят проксирование.

Пример проблемы:

@Service
public class UserService {
    public void nonTransactionalMethod() {
        // Внутренний вызов - транзакция НЕ создается
        transactionalMethod();
    }

    @Transactional
    public void transactionalMethod() {
        // Операции с БД без транзакционной защиты
    }
}

Решения:

  1. Вынести в отдельный сервис (рекомендуется):

    @Service
    class TransactionalService {
    @Transactional
    public void transactionalMethod() { /* ... */ }
    }
  2. Использовать self-injection (осторожно):

    
    @Autowired
    private UserService self;

public void nonTransactionalMethod() { self.transactionalMethod(); // Теперь работает через прокси }


3. **Программное управление через TransactionTemplate:**
```java
@Autowired
private TransactionTemplate transactionTemplate;

public void nonTransactionalMethod() {
    transactionTemplate.execute(status -> {
        // транзакционный код
        return null;
    });
}
  1. Использовать AspectJ mode (менее распространено):
    spring.aop.proxy-target-class=false