Ответ
Transaction Propagation определяет границы транзакции при вызове одного @Transactional-метода из другого. Это политика, управляющая тем, как должен вести себя метод: использовать существующую транзакцию, создать новую или работать без неё.
Типы распространения (Propagation.*):
- REQUIRED (по умолчанию) – Использует активную транзакцию, если она есть. Если нет – создаёт новую.
- REQUIRES_NEW – Всегда создаёт новую, независимую транзакцию. Текущая транзакция приостанавливается.
- SUPPORTS – Работает в контексте существующей транзакции, если она есть. Если нет – выполняется без транзакции.
- NOT_SUPPORTED – Выполняется без транзакции. Активная транзакция приостанавливается на время работы метода.
- MANDATORY – Требует активной транзакции. Если её нет – выбрасывается исключение
IllegalTransactionStateException. - NEVER – Запрещает выполнение в транзакции. Если активная транзакция существует – выбрасывается исключение.
- NESTED – Создаёт вложенную транзакцию (точку сохранения) внутри существующей, если она есть. Откат вложенной транзакции не приводит к откату внешней. Поддерживается не всеми менеджерами транзакций (например, работает с
DataSourceTransactionManager).
Пример использования:
@Service
public class UserService {
@Transactional(propagation = Propagation.REQUIRED)
public void createUser(User user) {
// Использует или создаёт транзакцию
userRepository.save(user);
updateAuditLog(user); // Вызов метода с другой политикой
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateAuditLog(User user) {
// Всегда выполняется в новой, независимой транзакции
auditLogRepository.save(new AuditLog("USER_CREATED", user.getId()));
}
}
Почему это важно: Правильный выбор политики предотвращает непредсказуемое поведение (например, откат всей бизнес-операции из-за исключения в логгировании) и управляет изоляцией операций.