Ответ
Propagation Type определяет, как должна вести себя транзакция, если она вызывается в контексте уже существующей транзакции. Это поведение задаётся через атрибут propagation аннотации @Transactional.
Основные типы распространения (значения Propagation):
| Тип | Поведение | Когда использовать |
|---|---|---|
REQUIRED (по умолчанию) |
Использует текущую транзакцию, если она есть. Если нет — создаёт новую. | Большинство операций в сервисном слое. |
REQUIRES_NEW |
Всегда создаёт новую транзакцию. Приостанавливает текущую, если она существует. | Операции логирования или аудита, которые должны быть сохранены даже при откате основной бизнес-транзакции. |
SUPPORTS |
Работает в текущей транзакции, если она есть. Если нет — выполняется без транзакции. | Операции чтения, которые могут работать как в транзакционном, так и в нетранзакционном контексте. |
NOT_SUPPORTED |
Выполняется без транзакции. Приостанавливает текущую транзакцию, если она есть. | Вызов методов, несовместимых с транзакциями (например, работа с JMS). |
MANDATORY |
Требует активной транзакции. Если её нет — выбрасывается исключение. | Методы, которые должны вызываться только в рамках существующей транзакции. |
NEVER |
Требует отсутствия транзакции. Если она есть — выбрасывается исключение. | Проверка, что метод не вызывается в транзакционном контексте. |
NESTED |
Создаёт вложенную транзакцию внутри текущей. Откат вложенной не приводит к откату внешней (если не используется REQUIRED). |
Сложные операции, где часть шагов может быть откатана независимо. Поддерживается не всеми СУБД (требует savepoints). |
Пример:
@Service
public class OrderService {
@Transactional(propagation = Propagation.REQUIRED)
public void placeOrder(Order order) {
// Основная бизнес-логика
logAudit(order); // Вызов метода с REQUIRES_NEW
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logAudit(Order order) {
// Запись в лог-таблицу. Сохранится, даже если placeOrder откатится.
}
}