Питання 20 · Розділ 16

Як працюють каскадні операції (Cascade)

Cascading (каскадування) в JPA — механізм автоматичного поширення операцій, що виконуються над батьківською сутністю, на всі пов'язані з нею дочірні сутності. Це дозволяє управл...

Мовні версії: English Russian Ukrainian

Огляд

Cascading (каскадування) в JPA — механізм автоматичного поширення операцій, що виконуються над батьківською сутністю, на всі пов’язані з нею дочірні сутності. Це дозволяє управляти цілими графами об’єктів через один виклик методу EntityManager.


🟢 Junior Level

Що таке Cascade

Cascade — автоматично поширює операції з батьківської сутності на пов’язані.

@Entity
public class Order {
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> items;
}

Order order = new Order();
OrderItem item = new OrderItem();
order.getItems().add(item);

entityManager.persist(order);  // persist викличеться і для items!

CascadeTypes

CascadeType.ALL        всі операції (persist, merge, remove, refresh, detach)
CascadeType.PERSIST    тільки persist
CascadeType.MERGE      тільки merge
CascadeType.REMOVE     тільки remove
CascadeType.REFRESH    тільки refresh
CascadeType.DETACH     тільки detach

🟡 Middle Level

Cascade vs orphanRemoval

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items;

// Cascade — propagates операції (persist, merge, remove)
// orphanRemoval — видаляє entities які видалені з колекції

order.getItems().remove(0);  // orphanRemoval видалить item з БД!

// Ключова відмінність: CascadeType.REMOVE спрацьовує тільки при видаленні батька.
// orphanRemoval спрацьовує також при видаленні дитини з колекції,
// навіть якщо батько не видалений.

Рекомендації щодо використання

@OneToMany (composite):  CascadeType.ALL + orphanRemoval = true
@ManyToOne:              CascadeType.PERSIST, MERGE (або без cascade)
@OneToOne:               CascadeType.ALL
@ManyToMany:             CascadeType.PERSIST, MERGE

Типові помилки

// ❌ Cascade.ALL для @ManyToOne
@ManyToOne(cascade = CascadeType.ALL)
private User user;

// При видаленні Order → видалиться User!
entityManager.remove(order);  // ❌ cascade.REMOVE → User видалено

// ✅ Без cascade для shared entities
@ManyToOne
private User user;  // User управляється окремо

JPA Cascade vs DB Cascade

JPA Cascading:
- Виконується кодом Hibernate
- Hibernate повинен знати про всі об'єкти в пам'яті
- Зручно для об'єктно-орієнтованої логіки

DB Cascading (ON DELETE CASCADE):
- Виконується рушієм СУБД
- Відбувається швидше
- Гарантує цілісність при прямих SQL запитах

🔴 Senior Level

Внутрішня реалізація

Cascade process:
1. При операції на parent (persist, merge, remove)
2. Hibernate обходить всі пов'язані entities
3. Для кожного child — застосовує операцію
4. Рекурсивно для nested зв'язків
5. Всі операції scheduled в persistence context
6. При flush — виконуються в правильному порядку

Каскадування в Many-to-Many

// ❌ Cascade.REMOVE в Many-to-Many — небезпечно!
@Entity
public class Author {
    @ManyToMany(cascade = CascadeType.ALL)
    private List<Book> books;
}

// Видалення Author → видалення всіх книг → видалення інших Authors
// Видалення Author з cascade=ALL видалить всі Books цього автора.
// Якщо у Books теж є cascade=ALL до Author — видалиться і другий автор, і його книги.

// ✅ Без REMOVE для Many-to-Many
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Book> books;

Best Practices

✅ CascadeType.ALL для композицій (child не має сенсу без parent)
✅ PERSIST, MERGE для асоціацій (shared entities)
✅ orphanRemoval для composite children
✅ Без REMOVE для shared entities
✅ DB-level cascade для великих видалень

❌ CascadeType.ALL для @ManyToOne
❌ Cascade.REMOVE для shared entities
❌ Cascade.REMOVE в Many-to-Many
❌ Каскадне видалення великих колекцій через JPA

🎯 Шпаргалка для співбесіди

Обов’язково знати:

  • Cascade автоматично поширює операції (persist, merge, remove) на пов’язані сутності
  • CascadeType.ALL — всі операції, PERSIST/MERGE/REMOVE — окремі типи
  • CascadeType.ALL для композицій (Order → OrderItem), PERSIST/MERGE для асоціацій (Order → User)
  • Cascade.REMOVE для @ManyToOne — небезпечно: видалення Order видалить User
  • Каскади JPA працюють тільки з Managed-об’єктами

Пов’язані теми:

  • [[21. Які типи Cascade існують]]
  • [[22. Що таке orphan removal]]
  • [[23. Як правильно використовувати @OneToMany і @ManyToOne]]
  • [[7. Опишіть життєвий цикл Entity в Hibernate]]