Что такое уровни распространения (propagation) транзакций в Spring?

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

Ответ

Уровни распространения (propagation) в Spring определяют поведение транзакции при вложенных вызовах методов, помеченных @Transactional.

7 уровней propagation в Spring:

Уровень Описание Когда использовать
REQUIRED (по умолчанию) Использует существующую транзакцию или создаёт новую Большинство случаев, стандартное поведение
REQUIRES_NEW Всегда создаёт новую транзакцию, приостанавливая текущую Независимые операции (логирование, аудит)
NESTED Создаёт вложенную savepoint-транзакцию Частичный откаток в рамках основной транзакции
MANDATORY Требует активной транзакции, иначе исключение Методы, которые должны вызываться в транзакционном контексте
SUPPORTS Работает в транзакции, если она есть Операции чтения, которые могут работать без транзакции
NOT_SUPPORTED Выполняется без транзакции, приостанавливая текущую Методы, несовместимые с транзакциями (отправка email)
NEVER Требует отсутствия транзакции, иначе исключение Проверка, что метод не вызывается в транзакции

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

@Service
public class OrderService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void createOrder(Order order) {
        // Использует текущую транзакцию или создаёт новую
        orderRepository.save(order);

        // Независимая операция логирования
        logActivity(order);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logActivity(Order order) {
        // Всегда выполняется в НОВОЙ транзакции
        // Откат не повлияет на основную транзакцию createOrder
        auditLogRepository.save(new AuditLog("Order created", order.getId()));
    }
}

Важные особенности:

  • NESTED работает только с некоторыми СУБД (не поддерживается в JPA/Hibernate)
  • REQUIRES_NEW требует нового соединения с БД из пула
  • При использовании NOT_SUPPORTED/NEVER текущая транзакция приостанавливается

Рекомендации:

  1. Используйте REQUIRED по умолчанию
  2. REQUIRES_NEW — для независимых побочных операций
  3. MANDATORY — для строгого контроля вызова методов
  4. Избегайте смешивания разных уровней без понимания последствий