Ответ
Аннотация @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.
Проверка: Убедитесь, что:
- Класс является Spring-бином (
@Service,@Componentи т.д.) - Включена обработка аннотаций (
@EnableTransactionManagement) - Метод вызывается извне класса (через прокси)