Для чего используется параметр propagation в аннотации @Transactional в Spring?

«Для чего используется параметр propagation в аннотации @Transactional в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Параметр propagation определяет поведение транзакции при её вызове из другого транзакционного метода. Он управляет тем, как должна вести себя новая транзакция в контексте существующей.

Основные значения:

  • REQUIRED (по умолчанию): Использует существующую транзакцию, если она есть, или создаёт новую.
  • REQUIRES_NEW: Всегда создаёт новую транзакцию, приостанавливая текущую, если она существует.
  • SUPPORTS: Выполняется в транзакции, если она есть, иначе — без транзакции.
  • NOT_SUPPORTED: Выполняет метод без транзакции, приостанавливая текущую, если она есть.
  • MANDATORY: Требует активной транзакции, иначе выбрасывает исключение.
  • NEVER: Требует отсутствия транзакции, иначе выбрасывает исключение.
  • NESTED: Создаёт вложенную транзакцию внутри существующей (работает, если БД поддерживает savepoints).

Пример использования REQUIRES_NEW:

@Service
public class OrderService {
    @Transactional(propagation = Propagation.REQUIRED)
    public void placeOrder(Order order) {
        // Основная логика заказа
        saveOrder(order);
        // Логирование должно быть независимо от отката основной транзакции
        logAuditEvent(order);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logAuditEvent(Order order) {
        // Эта запись в лог-таблицу будет сохранена,
        // даже если основная транзакция placeOrder откатится
        auditRepository.save(new AuditEvent("Order placed", order.getId()));
    }
}

Почему это важно: Правильный выбор propagation предотвращает непредсказуемое поведение (например, нежелательный откат логирования или блокировку данных) и обеспечивает атомарность операций на нужном уровне.