Что такое каскадные операции (Cascade) в JPA/Hibernate?

Ответ

Каскадные операции в JPA/Hibernate — это механизм, который позволяет автоматически распространять операции управления жизненным циклом (persist, merge, remove и др.) с родительской сущности на связанные с ней дочерние сущности.

Зачем это нужно: Упрощает код, избавляя от необходимости вручную сохранять, обновлять или удалять каждую связанную сущность.

Типы каскадных операций (перечисление CascadeType):

  • PERSIST – Сохранение родителя приводит к сохранению детей.
  • MERGE – Обновление (слияние) родителя приводит к обновлению детей.
  • REMOVE – Удаление родителя приводит к удалению детей.
  • REFRESH – Обновление состояния родителя из БД приводит к обновлению детей.
  • DETACH / EVICT – Отсоединение родителя приводит к отсоединению детей.
  • ALL – Все перечисленные выше операции.

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

@Entity
public class Order {
    @Id
    @GeneratedValue
    private Long id;

    // При сохранении, обновлении или удалении Order,
    // те же операции применятся ко всем элементам OrderItem в коллекции.
    @OneToMany(mappedBy = "order", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private List<OrderItem> items = new ArrayList<>();

    // ... геттеры и сеттеры
}

@Entity
public class OrderItem {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;

    // ... геттеры и сеттеры
}

Код без каскада (громоздкий):

em.persist(order); // Сохраняем Order
for (OrderItem item : order.getItems()) {
    em.persist(item); // Вручную сохраняем каждый OrderItem
}

Код с каскадом (простой):

em.persist(order); // Автоматически сохранит и Order, и все OrderItem

Важное предупреждение: Будьте осторожны с CascadeType.REMOVE. Удаление родителя может привести к массовому каскадному удалению множества дочерних записей, что может быть неочевидно и негативно сказаться на производительности.

Ответ 18+ 🔞

Ну, слушай, про каскады в Hibernate, это ж классика, блядь! Сидишь такой, пишешь свой Order, туда-сюда, а потом понимаешь — чтобы каждый OrderItem сохранить, надо в цикле за ним бегать, как за маленьким, блядь, пиздёнышем. Заебись работа, да? Рутина ебаная!

А оказывается, есть же волшебная палочка — cascade. Берёшь эту аннотацию, и как бабка над горохом нашептала: сохранил Order один раз, а все его items сами, сука, как по маслу, в базу записались. Красота, ёпта!

Смотри, какие штуки есть в CascadeType, это как меню в столовой, выбирай, что тебе надо:

  • PERSIST — сохранил папу, детки автоматически подтянутся. Не надо за каждым бегать.
  • MERGE — обновил папу, и детишки подтянулись. Удобно, блядь.
  • REMOVE — вот это, сука, самая опасная штука! Удалил заказ — и все позиции в нём нахуй полетели в небытие. Один неверный движ — и половина базы, как Муму, на дно. Терпения ноль ебать, когда такое в проде случается!
  • REFRESH, DETACH — уже более специфичные приколы, но тоже могут пригодиться.
  • ALL — ну это, блядь, полный абзац, давай всё и сразу, похуй!

Вот смотри, как это выглядит в коде, чтобы не быть, прости господи, распиздяем:

@Entity
public class Order {
    @Id
    @GeneratedValue
    private Long id;

    // Внимание на магию! Говорим: "Эй, Hibernate, всё что я делаю с Order — делай и с items!"
    @OneToMany(mappedBy = "order", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private List<OrderItem> items = new ArrayList<>();
}

Без каскада (старорежимный ужас):

em.persist(order); // Записали заказ
for (OrderItem item : order.getItems()) {
    em.persist(item); // А теперь, сука, попляши с каждым айтемом отдельно! Заебался уже...
}

С каскадом (цивилизация, блядь!):

em.persist(order); // Щёлк — и всё, пиздец. И заказ, и все его items уже в базе. Ебушки-воробушки!

Но запомни, как "Отче наш": CascadeType.REMOVE — это хуй с горы. Один неаккуратный em.remove(order) — и у тебя половина таблицы order_item накрылась медным тазом. Подозрение ебать чувствую, когда вижу его в необдуманных местах. Сначала думай, э, бошка, думай, а потом уже каскадируй на удаление, а то будет тебе волнение ебать, когда продакшн упадёт.