Home > Spring > πŸƒ[Spring] JPAμ—μ„œμ˜ Cascade μ˜΅μ…˜

πŸƒ[Spring] JPAμ—μ„œμ˜ Cascade μ˜΅μ…˜
Spring Framework

πŸƒ[Spring] JPAμ—μ„œμ˜ Cascade μ˜΅μ…˜.

  • JPAμ—μ„œ Cascade μ˜΅μ…˜μ€ μ—”ν‹°ν‹° κ°„μ˜ μ—°κ΄€κ΄€κ³„μ—μ„œ νŠΉμ • 엔티티에 μˆ˜ν–‰λœ μž‘μ—…(μ €μž₯, μ‚­μ œ λ“±)이 μ—°κ΄€λœ λ‹€λ₯Έ 엔티티에 ν•¨κ»˜ μ μš©λ˜λ„λ‘ μ„€μ •ν•˜λŠ” μ˜΅μ…˜μž…λ‹ˆλ‹€.
    • 즉, λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ νŠΉμ • μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ μžμ‹ 엔티티도 λ™μΌν•œ μž‘μ—…μ΄ μžλ™μœΌλ‘œ μ „νŒŒλ˜κ²Œ λ§Œλ“­λ‹ˆλ‹€.

1️⃣ Cascade μ˜΅μ…˜μ˜ μ’…λ₯˜.

  • Cascade μ˜΅μ…˜μ—λŠ” μ—¬λŸ¬ 가지 μ’…λ₯˜κ°€ 있으며, 각각의 μ˜΅μ…˜μ€ λ‹€λ₯Έ μž‘μ—…μ„ μ „νŒŒν•©λ‹ˆλ‹€.

1️⃣ CascadeType.PERSIST

  • λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ μ €μž₯될 λ•Œ, μ—°κ΄€λœ μžμ‹ 엔티티도 ν•¨κ»˜ μ €μž₯λ©λ‹ˆλ‹€.
    • EntityManager.persist() 호좜 μ‹œ μžμ‹ 엔티티도 μžλ™μœΌλ‘œ persistλ©λ‹ˆλ‹€.

2️⃣ CascadeType.MERGE

  • λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ 병합될 λ•Œ, μ—°κ΄€λœ μžμ‹ 엔티티도 ν•¨κ»˜ λ³‘ν•©λ©λ‹ˆλ‹€.
    • 즉, EntityManager.merge() 호좜 μ‹œ μžμ‹ 엔티티도 μžλ™μœΌλ‘œ mergeλ©λ‹ˆλ‹€.

3️⃣ CascadeType.REMOVE

  • λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ μ‚­μ œλ  λ•Œ, μ—°κ΄€λœ μžμ‹ 엔티티도 ν•¨κ»˜ μ‚­μ œλ©λ‹ˆλ‹€.
    • EntityManager.remove() 호좜 μ‹œ μžμ‹ 엔티티도 μžλ™μœΌλ‘œ removeλ©λ‹ˆλ‹€.

4️⃣ CascadeType.REFRESH

  • λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ μƒˆλ‘œ 고침될 λ•Œ, μ—°κ΄€λœ μžμ‹ 엔티티도 ν•¨κ»˜ μƒˆλ‘œ κ³ μΉ¨λ©λ‹ˆλ‹€.
    • EntityManager.refresh() 호좜 μ‹œ μžμ‹ 엔티티도 refreshλ©λ‹ˆλ‹€.

5️⃣ CascadeType.DETACH

  • λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ μ€€μ˜μ† μƒνƒœλ‘œ 변경될 λ•Œ, μ—°κ΄€λœ μžμ‹ 엔티티도 ν•¨κ»˜ μ€€μ˜μ† μƒνƒœλ‘œ λ³€κ²½λ©λ‹ˆλ‹€.
    • EntityManager.detach() 호좜 μ‹œ μžμ‹ 엔티티도 μžλ™μœΌλ‘œ detachλ©λ‹ˆλ‹€.

6️⃣ CascadeType.ALL

  • μœ„μ˜ λͺ¨λ“  μ˜΅μ…˜μ„ μ μš©ν•˜μ—¬, λͺ¨λ“  μž‘μ—…(persist, merge, remove, refresh, detach)이 μžμ‹ 엔티티에 μ „νŒŒλ˜λ„λ‘ ν•©λ‹ˆλ‹€.

2️⃣ 예제: CascadeType.PERSIST와 CascadeType.REMOVE μ‚¬μš©.

  • λ‹€μŒ μ˜ˆμ œμ—μ„œλŠ” CascadeType.PERSIST와 CascadeType.REMOVEλ₯Ό μ‚¬μš©ν•˜μ—¬ λΆ€λͺ¨ μ—”ν‹°ν‹° Orderκ°€ μ €μž₯ 및 μ‚­μ œλ  λ•Œ, μ—°κ΄€λœ μžμ‹ μ—”ν‹°ν‹° OrderItem도 ν•¨κ»˜ μ €μž₯ 및 μ‚­μ œλ˜λŠ” 상황을 λ³΄μ—¬μ€λ‹ˆλ‹€.
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String customerName;
    
    @OneToMany(mappedBy = "order", cascade = {CascadeType.PERSIST, Cascade.REMOVE})
    private List<OrderItem> orderItems = new ArrayList<>();
    
    // 연관관계 편의 λ©”μ„œλ“œ
    public void addOrderItem(OrderItem item) {
        orderItems.add(item);
        item.setOrder(this);
    }
    
    // getter, setter
}

@Entity
public class OrderItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String productName;
    private int quantity;
    
    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;
    
    // getter, setter
}

πŸ‘‰ μ½”λ“œ μ„€λͺ….

  • Order μ—”ν‹°ν‹°μ—μ„œ orderItems ν•„λ“œλŠ” @OneToMany κ΄€κ³„λ‘œ μ„€μ •λ˜μ–΄ 있으며, casecade = {CascadeType.PERSIST, CascadeType.REMOVE} μ˜΅μ…˜μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
  • Order μ—”ν‹°ν‹°κ°€ persist될 λ•Œ OrderItem 엔티티도 ν•¨κ»˜ μ €μž₯되고, Order μ—”ν‹°ν‹°κ°€ μ‚­μ œλ  λ•Œ OrderItem 엔티티도 ν•¨κ»˜ μ‚­μ œλ©λ‹ˆλ‹€.

3️⃣ 예제 μ½”λ“œ μ‹€ν–‰.

Order order = new Order();
order.setCustomerName("Alice");

OrderItem item1 = new OrderItem();
item1.setProductName("Laptop");
item1.setQuantity(1);

OrderItem item2 = new OrderItem();
item2.setProductName("Mouse");
item2.setQuantity(2);

order.addOrderItem(item1);
order.addOrderItem(item2);

entityManager.persist(order); // Order와 OrderItem듀이 ν•¨κ»˜ μ €μž₯됨
  • μœ„ μ½”λ“œμ—μ„œ entityManager.persist(order)λ₯Ό ν˜ΈμΆœν•˜λ©΄ Order와 μ—°κ΄€λœ OrderItem 엔티티듀이 ν•¨κ»˜ μ €μž₯λ©λ‹ˆλ‹€.
    • 이후 entityManager.remove(order)λ₯Ό ν˜ΈμΆœν•˜λ©΄ Order와 OrderItem 엔티티듀이 ν•¨κ»˜ μ‚­μ œλ©λ‹ˆλ‹€.

4️⃣ Cascade μ˜΅μ…˜ μ‚¬μš© μ‹œ 주의 사항.

  • CascadeType.REMOVEλŠ” λΆ€λͺ¨ μ—”ν‹°ν‹°κ°€ μ‚­μ œλ  λ•Œ μžμ‹ 엔티티도 μ‚­μ œλ˜λ―€λ‘œ, λΆˆν•„μš”ν•œ 데이터 μ‚­γ…ˆλ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ μ‹ μ€‘ν•˜κ²Œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • 연관관계가 λ³΅μž‘ν•  경우 CascadeType.ALL을 μ‚¬μš©ν•˜λ©΄ μ˜λ„μΉ˜ μ•Šμ€ 연쇄적 μž‘μ—…μ΄ λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ, κΌ­ ν•„μš”ν•œ μ˜΅μ…˜λ§Œ μ„ νƒμ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.
  • μ–‘λ°©ν–₯ μ—°κ΄€κ΄€κ³„μ—μ„œ μˆœν™˜ μ°Έμ‘° λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ μ£Όμ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

5️⃣ μš”μ•½.

  • Cascade μ˜΅μ…˜μ€ λΆ€λͺ¨ 엔티티에 μˆ˜ν–‰λœ μž‘μ—…μ΄ μžμ‹ 엔티티에 μžλ™μœΌλ‘œ μ „νŒŒλ˜λ„λ‘ μ„€μ •ν•˜λŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€.
  • 각 μ˜΅μ…˜(PRESIST, MERGE, REMOVE, REFRESH, DETACH, ALL)은 νŠΉμ • μž‘μ—…μ— λŒ€ν•œ μ „νŒŒ 방식을 μ •μ˜ν•©λ‹ˆλ‹€.
  • Cascade μ˜΅μ…˜μ€ 데이터 일관성 μœ μ§€μ— 도움이 λ˜μ§€λ§Œ, λΆˆν•„μš”ν•œ μ „νŒŒλ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ μ‹ μ€‘ν•˜κ²Œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.