Когда аннотация @Transactional может не работать в Spring?

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

Ответ

Аннотация @Transactional в Spring может не сработать в следующих случаях:

1. Внутренний вызов метода в том же классе Spring AOP использует прокси-объекты, поэтому вызов @Transactional-метода из другого метода того же класса обходит прокси.

@Service
public class UserService {
    public void updateUser(Long id) {
        // Этот вызов НЕ будет транзакционным!
        updateUserInternal(id);
    }

    @Transactional
    public void updateUserInternal(Long id) {
        // Логика обновления
    }
}

2. Неправильный тип исключения По умолчанию откат транзакции происходит только для RuntimeException и Error.

@Transactional
public void saveData() throws IOException {
    // Если выбросится IOException, транзакция НЕ откатится
    throw new IOException("File error");
}
// Решение: @Transactional(rollbackFor = Exception.class)

3. Исключение перехвачено внутри метода

@Transactional
public void process() {
    try {
        // Операция, которая может вызвать исключение
    } catch (Exception e) {
        // Транзакция НЕ откатится, так как исключение перехвачено
    }
}

4. Метод объявлен как private, final или static Spring не может создать прокси для таких методов.

5. Отсутствует менеджер транзакций В конфигурации должен быть бин PlatformTransactionManager.

6. Неправильная propagation

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void nonTransactionalMethod() {
    // Метод всегда выполняется без транзакции
}

7. Работа в отдельном потоке Транзакция привязана к текущему потоку через ThreadLocal.

Проверка: Убедитесь, что:

  1. Класс является Spring-бином (@Service, @Component и т.д.)
  2. Включена обработка аннотаций (@EnableTransactionManagement)
  3. Метод вызывается извне класса (через прокси)