cascade = CascadeType.ALL
의 의미:
부모 엔티티의 저장, 수정, 삭제 같은 상태 변화를 자식 엔티티에게 자동으로 전파한다.
주로 사용하는 경우:
✅ 부모와 자식의 생명주기가 동일할 때
✅ 자식이 부모 없이 의미가 없을 때
대표적인 예:
Order
|
├── OrderItem
|
└── Delivery
같은 도메인입니다.
반대로:
Member
|
Order
처럼 독립적으로 관리해야 하는 데이터에는 신중하게 사용해야 합니다.
cascade = CascadeType.ALL은 부모 엔티티의 상태 변화를 자식 엔티티에게 자동으로 전파하기 위해 사용합니다.
쉽게 말하면:
"부모를 저장하거나 삭제할 때, 연결된 자식도 같이 처리해줘"
라는 의미입니다.
1. Cascade가 필요한 상황
예를 들어 주문 시스템을 생각해보겠습니다.
@Entity
public class Order {
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
}
주문(Order)과 주문 상품(OrderItem)이 있습니다.
관계:
Order (주문)
|
| 1:N
|
OrderItem (주문상품)
데이터:
Order
id = 1
주문자 = "kim"
OrderItem
id = 10
상품 = "노트북"
OrderItem
id = 11
상품 = "마우스"
2. Cascade가 없으면?
cascade가 없다면 저장할 때 이렇게 해야 합니다.
Order order = new Order();
OrderItem item1 = new OrderItem();
OrderItem item2 = new OrderItem();
order.addOrderItem(item1);
order.addOrderItem(item2);
orderRepository.save(order);
orderItemRepository.save(item1);
orderItemRepository.save(item2);
부모와 자식을 각각 저장해야 합니다.
3. CascadeType.ALL을 사용하면?
Order order = new Order();
OrderItem item1 = new OrderItem();
OrderItem item2 = new OrderItem();
order.addOrderItem(item1);
order.addOrderItem(item2);
orderRepository.save(order);
이 한 줄만 실행해도:
Order 저장
↓
OrderItem 저장
↓
OrderItem 저장
자동으로 전파됩니다.
CascadeType.ALL이 의미하는 것
ALL은 여러 cascade 옵션을 모두 포함합니다.
실제로는:
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE,
CascadeType.REMOVE,
CascadeType.REFRESH,
CascadeType.DETACH
}
와 같습니다.
대표적인 것만 보면:
옵션의미
| PERSIST | 부모 저장 시 자식도 저장 |
| REMOVE | 부모 삭제 시 자식도 삭제 |
| MERGE | 부모 수정 시 자식도 병합 |
| REMOVE | 삭제 전파 |
4. 실무에서 가장 많이 쓰는 경우
① 부모와 자식의 생명주기가 같은 경우
예:
주문(Order)
|
├── 주문상품(OrderItem)
├── 배송(Delivery)
주문이 없으면 주문상품도 의미가 없습니다.
즉:
Order 생성
↓
OrderItem 생성
Order 삭제
↓
OrderItem 삭제
같이 움직여야 합니다.
그래서:
@OneToMany(
mappedBy = "order",
cascade = CascadeType.ALL
)
private List<OrderItem> orderItems;
를 사용합니다.
② 일대일 관계
예:
회원(Member)
|
주소(Address)
회원만 존재하고 주소만 따로 존재할 필요가 없다면:
@OneToOne(
cascade = CascadeType.ALL
)
private Address address;
사용 가능합니다.
하지만 모든 곳에 CascadeType.ALL을 쓰면 안 됩니다
예를 들어:
회원(Member)
|
주문(Order)
관계에서:
@OneToMany(
cascade = CascadeType.ALL
)
private List<Order> orders;
이렇게 하는 것은 위험합니다.
왜냐하면:
회원 삭제
↓
모든 주문 삭제
가 되어버립니다.
하지만 실제 서비스에서는 주문 데이터는 법적으로 보관해야 할 수도 있습니다.
Cascade와 orphanRemoval 차이
둘은 자주 같이 헷갈립니다.
Cascade
부모 자체가 변경될 때 전파
예:
orderRepository.delete(order);
결과:
Order 삭제
↓
OrderItem 삭제
orphanRemoval
컬렉션에서 제거된 자식을 삭제
예:
order.getOrderItems().remove(item);
결과:
OrderItem이 컬렉션에서 빠짐
↓
DB에서도 삭제
'Spring&IntelliJ' 카테고리의 다른 글
| @Embeddable에 대해서 (0) | 2026.06.16 |
|---|---|
| @Inheritance에 대해서 (3가지 전략) (0) | 2026.06.16 |
| h2 파일 생성 실패시, Database not found 애러 해결방법 (0) | 2026.06.05 |
| JPA 지연로딩과 프록시객체 (0) | 2026.06.02 |
| 1. 쓰기 지연과 지연 로딩에 대해서, 2.로우(ROW)락과 쓰기지연에 대해서 (0) | 2026.06.02 |