Cascade
JPA에서 Cascade란 부모 엔티티와 관련된 자식 엔티티의 상태 변화를 전파시키는 옵션입니다. 즉, 부모 엔티티의 상태가 변경되면, 자식 엔티티의 상태도 같이 변경되도록 자동으로 처리해 주는 기능입니다.
Cascade의 장단점
Cascade를 사용하면 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있어서 코드를 간략화하고 편리하게 사용할 수 있습니다. 또한, 저장, 삭제, 수정 등을 한 번에 처리할 수 있기 때문에 효율적입니다.
하지만, Cascade를 사용하면 자식 엔티티를 저장할 때 부모 엔티티가 먼저 저장되어 있어야 하기 때문에 이를 고려하여 코드를 작성해야 합니다. 또한, 자식 엔티티를 일괄적으로 처리하기 때문에 필요하지 않은 자식 엔티티까지 저장되는 경우가 생길 수 있습니다. 이를 방지하기 위해서는 적절한 cascade 옵션을 선택하여 사용해야 합니다.
[Cascade 예시 코드]
부모 엔티티인 Member를 저장할 때, cascade 옵션을 이용하여 자식 엔티티인 Order와 Payment도
함께 저장할 수 있습니다.
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<Order> orders = new ArrayList<>();
}
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<Payment> payments = new ArrayList<>();
}
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private Order order;
}
// 부모 엔티티 저장 시 cascade를 사용하여 자식 엔티티도 함께 저장
public void saveMember(Member member) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
em.persist(member);
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
em.close();
}
}
EntityManager.persist()란?
EntityManager.persist() 메서드는 JPA에서 데이터베이스에 새로운 엔티티를 저장하는 메서드입니다.
'persist()' 메서드를 호출하면, 해당 엔티티를 데이터베이스에 새로 저장합니다.
이때 영속성 컨텍스트에도 해당 엔티티를 저장하므로, 이후에 엔티티를 조회하면 영속성 콘텍스트에서 먼저 조회합니다.
이를 통해 성능상 이점을 가져올 수 있습니다.
EntityManager.persist()의 장단점
EntityManager.persist() 메서드의 장점은 다음과 같습니다.
- 새로운 엔티티를 저장할 때 사용할 수 있으므로, JPA를 이용한 데이터베이스 저장이 간편해집니다.
- persist() 메서드를 사용하면, EntityManager가 영속성 컨텍스트에서 해당 엔티티를 관리하므로, 불필요한 데이터베이스 접근을 줄일 수 있습니다.
하지만 EntityManager.persist() 메서드는 몇 가지 단점도 가지고 있습니다.
- EntityManager.persist() 메서드를 호출하면, 해당 엔티티를 데이터베이스에 새로 저장합니다. 이때 데이터베이스에 저장되기 전까지는 해당 엔티티의 ID 값을 알 수 없습니다.
- EntityManager.persist() 메서드를 사용할 때, 자식 엔티티가 있으면 따로 저장해주어야 합니다. 이때 엔티티의 수가 많아지면, 저장해주어야 할 엔티티의 수도 많아지므로 번거로워집니다.
- EntityManager.persist() 메서드는 해당 엔티티를 영속성 컨텍스트에 저장하는 것이므로, 메모리 사용량이 증가할 수 있습니다. 이를 해결하기 위해서는 적절한 시점에 EntityManager.flush() 메서드를 호출하여 영속성 콘텍스트의 변경 내용을 데이터베이스에 저장해주어야 합니다.
[EntityManager.persist() 예시 코드]
부모 엔티티인 Member를 저장할 때, 자식 엔티티인 Order와 Payment는 별도로 저장해주어야 합니다.
public void saveMember(Member member) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
em.persist(member);
for (Order order : member.getOrders()) {
em.persist(order);
for (Payment payment : order.getPayments()) {
em.persist(payment);
}
}
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
em.close();
}
}
EntityManager.persist()와 Cascade의 차이
EntityManager의 persist 메서드를 이용하여 부모 엔티티를 저장할 때, 자식 엔티티는 별도로 저장해주어야 합니다.
이는 Cascade를 사용하지 않았을 때와 유사합니다.
이 방법은 Cascade를 사용하는 것보다는 코드가 복잡하지만, 자식 엔티티를 선택적으로 처리할 수 있기 때문에,
불필요한 자식 엔티티를 저장하지 않을 수 있습니다.
따라서, Cascade를 사용할 것인지는 상황에 따라 다르며, 자식 엔티티를 일괄적으로 처리해야 할 경우에는 Cascade를 사용하는 것이 효율적이고, 선택적으로 처리해야 할 경우에는 EntityManager.persist()를 이용하는 것이 좋습니다.
'Spring' 카테고리의 다른 글
Java Spring_@Builder (0) | 2023.03.05 |
---|---|
Java Spring_ @Mapping (0) | 2023.03.05 |
Spring Framework_ApplicationEventPublisher,@EventListener (0) | 2023.03.03 |
Spring을 이용해 이메일 보내는 방법 (0) | 2023.03.02 |
Spring Data JPA _ 페이징처리 (0) | 2023.02.22 |