Ответ
Для корректной работы декларативного управления транзакциями через @Transactional в Spring необходимо выполнить несколько условий:
1. Конфигурация:
- Включить управление транзакциями с помощью аннотации
@EnableTransactionManagementв классе конфигурации (в Spring Boot это делается автоматически). - Настроить менеджер транзакций (например,
PlatformTransactionManager). В Spring Boot с JPA достаточно зависимостиspring-boot-starter-data-jpa, иJpaTransactionManagerсоздается автоматически.
2. Правильное объявление:
- Аннотацию
@Transactionalможно ставить на класс (все public методы становятся транзакционными) или на отдельный public-метод. - Метод должен быть public. Вызов
@Transactional-метода изнутри того же класса (self-invocation) не будет работать через AOP-прокси.
Пример минимальной конфигурации в Spring Boot:
@Service
public class UserService {
@Transactional // Транзакция начнется при входе в метод
public void updateUser(User user) {
// Работа с EntityManager или JpaRepository
// При успешном завершении — коммит, при исключении RuntimeException — откат
}
}
3. Механизм работы: Spring создает AOP-прокси вокруг бина. При вызове транзакционного метода прокси:
- Получает соединение/сессию из пула.
- Отключает auto-commit.
- Выполняет целевой метод.
- При успехе — коммитит транзакцию.
- При возникновении unchecked исключения (
RuntimeExceptionи его наследники) — откатывает транзакцию. Для checked исключений откат не происходит по умолчанию (можно настроить черезrollbackFor).
Ключевые атрибуты для настройки: propagation, isolation, timeout, readOnly, rollbackFor/noRollbackFor.