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

Ответ

Уровни распространения (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. Избегайте смешивания разных уровней без понимания последствий

Ответ 18+ 🔞

А, слушай, смотри, вот эти ваши propagation levels в Spring, блядь... Это ж как в семье, когда тёща приезжает, понимаешь? Каждый уровень — это разная степень ебалыча и ответственности.

Вот смотри, табличку тебе нарисовали, семь штук, как смертных грехов, блядь. Но главное запомни три, остальные так, для красоты, чтобы архитекторы понтоваться могли.

REQUIRED — это как по умолчанию, стандарт. Ну типа: «Мужики, транзакция есть? Есть? Ну окей, вписываюсь. Нет? Ёбта, ща создам, не ссы». 90% всех методов должны быть с ним, и нехуй мудохаться.

REQUIRES_NEW — это вот отдельная, блядь, песня. Это когда ты такой: «Ой, всё, нахуй, я сам по себе!». Сука, он текущую транзакцию приостанавливает, как будто на паузу ставит, и заводит свою, новую. И если в этой новой пиздец случится — откатится только она, а основная жить будет. Идеально для логирования или отправки каких-нибудь уведомлений в ад, которые не должны всё похерить, если сломаются.

@Transactional(propagation = Propagation.REQUIRES_NEW) // Внимание, блядь! Отдельная касса!
public void logActivity(Order order) {
    auditLogRepository.save(new AuditLog("Order created", order.getId()));
    // Упади тут — основному заказу похуй, он сохранится.
}

NESTED — это, сука, хитрая жопа. Типа вложенная транзакция через savepoint. Если в дочернем методе пиздец — откатывается не всё, а только до этой точки. Красиво, да? А НО! Блядь, работает не везде, JPA/Hibernate её часто не поддерживает, так что это как ковёр-самолёт — в сказках есть, а на деле хуй.

MANDATORY — это ультиматум. «Я, блядь, буду работать ТОЛЬКО если ты уже в транзакции. Иначе — исключение тебе в ебало, разгильдяй!». Для строгого контроля, чтобы не вызывали метод абы как.

SUPPORTS — пофигист. «Есть транзакция? Ок, работаю в ней. Нету? Ну и похуй, буду без неё». Чисто для чтения данных.

NOT_SUPPORTED — анархист, блядь. «Я ненавижу ваши транзакции!». Он приходит, текущую транзакцию — стоп, на паузу, и работает без неё. Например, чтобы файлы на диск писать или в внешний сервис стучаться.

NEVER — параноик. «Если я вижу активную транзакцию — я вызываю психиатра, то есть исключение!». Чтобы гарантировать, что метод не вызовут внутри транзакционного контекста.

Главный совет, нахуй: Не выёбывайся. Ставь REQUIRED и спи спокойно. REQUIRES_NEW юзай точечно, когда реально нужна изоляция. А про NESTED можешь рассказывать на собеседованиях, чтобы выглядеть умным, но в продакшене её не увидишь, ядрёна вошь. Остальные — так, нишевые прибамбасы для особо извращённых сценариев. Всё, разобрались, иди работай.