Ответ
Propagation.NESTED — это вариант распространения транзакций в Spring, который создает вложенную транзакцию (nested transaction) на основе точек сохранения (savepoints) в текущей физической транзакции.
Принцип работы:
- Если активной транзакции нет, поведение аналогично
Propagation.REQUIRED(создает новую). - Если активная транзакция существует, метод выполняется внутри вложенной транзакции (устанавливается savepoint).
- Откат вложенной транзакции откатывает изменения только к этому savepoint, не затрагивая внешнюю транзакцию.
- Фиксация вложенной транзакции происходит условно — изменения фиксируются в БД только при успешной фиксации внешней транзакции.
Пример:
@Service
public class OrderService {
@Transactional(propagation = Propagation.REQUIRED)
public void processOrder(Order order) {
// Основная логика заказа
updateInventory(order); // Вложенная транзакция
// Если здесь выбросится исключение, откатится ВСЁ (и inventory)
}
@Transactional(propagation = Propagation.NESTED)
public void updateInventory(Order order) {
// Логика обновления склада
// Если здесь исключение, откатится ТОЛЬКО updateInventory,
// но processOrder может продолжить обработку
}
}
Ключевые ограничения и особенности:
- Зависит от JDBC-драйвера: Работает только если драйвер БД (PostgreSQL, MySQL, Oracle и др.) поддерживает savepoints.
- Не поддерживается JTA: Нельзя использовать с распределенными транзакциями (JTA).
- Ограниченная поддержка в JPA: Поведение может отличаться. Для JPA предпочтительнее использовать отдельные транзакции (
REQUIRES_NEW) или компенсирующие действия. - Использование: Полезен для сценариев, где часть бизнес-логики может безопасно откатиться независимо от основной операции.