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

Які типи Cascade існують

JPA надає кілька типів каскадних операцій, кожен з яких контролює поширення конкретного типу операції на пов'язані сутності. Правильний вибір типу cascade — ключ до коректної ро...

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

Огляд

JPA надає кілька типів каскадних операцій, кожен з яких контролює поширення конкретного типу операції на пов’язані сутності. Правильний вибір типу cascade — ключ до коректної роботи з графами об’єктів.


🟢 Junior Level

Всі типи CascadeType

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

Приклад кожного

// PERSIST — збереження з children
@OneToMany(cascade = CascadeType.PERSIST)
private List<OrderItem> items;

entityManager.persist(order);  // → persist для всіх items

// MERGE — оновлення з children
@OneToMany(cascade = CascadeType.MERGE)
private List<OrderItem> items;

entityManager.merge(order);  // → merge для всіх items

// REMOVE — видалення з children
@OneToMany(cascade = CascadeType.REMOVE)
private List<OrderItem> items;

entityManager.remove(order);  // → remove для всіх items

// ALL — всі операції
@OneToMany(cascade = CascadeType.ALL)
private List<OrderItem> items;

Коли НЕ використовувати cascade взагалі

Не використовуйте cascade коли обидві сутності — aggregate roots з власним життєвим циклом. Наприклад, Order та Customer — це окремі агрегати, каскад між ними небезпечний.


🟡 Middle Level

Коли що використовувати

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

Composite vs Association

// Composite — child не існує без parent
@Entity
public class Order {
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items;  // OrderItem без Order не має сенсу
}

// Association — entities незалежні
@Entity
public class Order {
    @ManyToOne  // no cascade
    private User user;  // User існує незалежно від Order
}

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

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

entityManager.remove(order);  // ❌ User теж видалено!

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

entityManager.remove(product);  // ❌ Category видалена!

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

🔴 Senior Level

Матриця рішень

Зв’язок Cascade orphanRemoval Чому
@OneToMany (composite) ALL true Child не існує без parent
@ManyToOne (shared) PERSIST, MERGE false Entity управляється окремо
@OneToOne (composite) ALL true Один до одного, композиція
@ManyToMany PERSIST, MERGE false Shared entities, небезпечно видаляти

Best Practices

✅ ALL для composite children
✅ PERSIST, MERGE для shared entities
✅ Без REMOVE для shared entities
✅ orphanRemoval для composite children
✅ Матриця рішень для кожного зв'язку

❌ REMOVE для shared entities
❌ ALL для @ManyToOne
❌ Cascade.REMOVE в Many-to-Many

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

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

  • 6 типів CascadeType: ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH
  • ALL — всі операції, але небезпечний для @ManyToOne та Many-to-Many
  • Композиції (Order → OrderItem): CascadeType.ALL + orphanRemoval = true
  • Асоціації (Order → User): PERSIST, MERGE або без cascade

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

  • [[20. Як працюють каскадні операції (Cascade)]]
  • [[22. Що таке orphan removal]]
  • [[23. Як правильно використовувати @OneToMany і @ManyToOne]]
  • [[24. У чому особливості bidirectional relationships]]