JPA - 고아 Entity 삭제

2024. 8. 29. 09:45JPA

 

2024/08/29

 

※   고아 Entity에 대해 알아보자.

 

   ▶  OrphanRemoval

📌 고아 객체(Orphan) 제거란?

        JPA는 부모  엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이것을 고아 객체 제거 라 한다. 이 기능을 사용해서 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제된다.


           ●  CASCADE의 REMOVE 옵션을 적용하면 해당 Entity 객체를 삭제 했을 때 연관된 Entity 객체들을 자동으로 삭제할 수 있었다.
              ○  하지만 REMOVE 옵션 같은 경우 연관된 Entity와 관계를 제거했다고 해서 자동으로 해당 Entity가 삭제 되지는 않는다.

     ➡️ OrphanTest

@Test
@Transactional
@Rollback(value = false)
@DisplayName("연관관계 제거")
void test1() {
    // 고객 Robbie 를 조회합니다.
    User user = userRepository.findByName("Robbie");
    System.out.println("user.getName() = " + user.getName());

    // 연관된 음식 Entity 제거 : 후라이드 치킨
    Food chicken = null;
    for (Food food : user.getFoodList()) {
        if(food.getName().equals("후라이드 치킨")) {
            chicken = food;
        }
    }
    if(chicken != null) {
        user.getFoodList().remove(chicken);
    }

    // 연관관계 제거 확인
    for (Food food : user.getFoodList()) {
        System.out.println("food.getName() = " + food.getName());
    }
}

           ●  후라이드 치킨 Entity 객체와 연관관계를 제거했지만 Delete SQL이 수행되지 않는 것을 확인할 수 있다.

 

✅  JPA에서는 이를 간편하게 처리할 수 있는 방법으로 orphanRemoval 옵션을 제공한다.

@Entity
@Getter
@Setter
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List<Food> foodList = new ArrayList<>();

    public void addFoodList(Food food) {
        this.foodList.add(food);
        food.setUser(this);// 외래 키(연관 관계) 설정
    }
}

           ●  orphanRemoval 옵션을 설정해준 후 다시한번 확인해 보자.
           ●  Delete SQL이 수행되어 후라이드 치킨 데이터가 삭제된 것을 확인할 수 있다.
           ●  추가로 orphanRemoval 옵션도 REMOVE 옵션과 마찬가지로 해당 Entity 즉, Robbie Entity 객체를 삭제하면 연관된 음식 Entity들이 자동으로 삭제된다.

 

⚠️ 고아 객체 제거 사용 시 주의사항❗

     👉  orphanRemoval이나 REMOVE 옵션을 사용할 때 삭제하려고 하는 연관된 Entity를 다른 곳에서 참조하고 있는지 아닌지를 꼭 확인해야한다.
         ●  A와 B에 참조되고 있던 C를 B를 삭제하면서 같이 삭제하게 되면 A는 참조하고 있던 C가 사라졌기 때문에 문제가 발생할 수 있다.
         ●  따라서 orphanRemoval 같은 경우 @ManyToOne 같은 애너테이션에서는 사용할 수 없다.
           ✅  @ManyToOne이 설정된 Entity는 해당 Entity 객체를 참조하는 다른 Entity 객체들이 있을 수 있기 때문에 속성으로 orphanRemoval를 가지고 있지 않다.

 

 

 

'JPA' 카테고리의 다른 글

스프링 - JPA 지연로딩  (1) 2024.08.27