JPA

[JPA] 고아객체? 그게 먼데

엄지성 2024. 7. 31. 23:56

고아 객체

 

스프링에서 엔티티끼리 연관관계를 연결하는 것은 매우 흔한 일이다.

그래서 JPA는 부모 엔티티와 연관관계가 끊어져버린 자식 엔티티를 자동으로 삭제해 주는 기능을 고아 객체 제거라고 한다.

// 고아 객체를 ORPHAN이라고 하기도 함

 

이러한 기능을 JPA에서 제공하니 안 써볼 수 없을 것이다.

그러니 이러한 기능을 사용한 코드를 살펴보자.


사용 예시

@Entity
public void Parent {

    @Id
    @GeneratedValue
    private Long id;
    
    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> children = new ArrayList<Child>();
    
    ....
}

 

위에 코드를 보면 고아 객체 제거 기능을 사용하기 위해 @OneToMany의 컬렉션에 `orphanRemoval = true`를 설정한 것을 볼 수 있다.

이러하면 컬렉션에서 제거한 엔티티는 자동으로 Delete 되게 된다.

사용 코드

Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0);

이러한 코드를 실행 시키면 

DELETE FROM CHILD WHERE ID=?

위와 같은 SQL이 생성되게 된다.

 

다시 돌아가 사용한 코드를 살펴보면 컬렉션에서 0번째, 즉 첫 번째 자식을 제거한 것이다.

`orphanRemoval = true`으로 엔티티를 제거하게 되면 데이터베이스에도 똑같이 제거되게 된다.

이 기능은 영속성 컨텍스트를 flush 할 때 SQL이 적용되기 때문에 flush 시점에서 위에 생성된 SQL이 날아가게 된다.

 

만약 위에 사용 코드처럼 하나씩 삭제 하는 것이 아닌 모든 컬렉션의 엔티티를 삭제하고 싶을 때에는

parent1.getChildren().clear();

이렇게 작성한다면 컬렉션의 엔티티를 비워 아무것도 들어있지 않게 된다.


정리

다시 리마인드 하자면 고아 객체 삭제는 참조가 제거되어 버린 엔티티를 다른 곳에서도 참조하지 않는 고아 객체로 인식하고 삭제하는 기능이다. 이 말은 참조하는 곳이 하나일 때만 사용하는 것이 올바르다. 쉽게 이야기하자면 게시물이 있고 댓글이 있다면 Board와 Comment와

양방향 매핑이 되어있다고 가정하면 이러한 상황에 사용하는 것과 비슷하다. 이러한 것과 반대로 만약 삭제한 엔티티를 다른 곳에서도 참조하였다고 하면 이 기능을 사용하기에는 올바르지 않다. 그러한 이유로 이 기능은 `@OneToOne`, `@OneToMany`에만 사용 가능하다.

 

또한 지금까지 설명한 기능을 개념적으로 보면 부모를 삭제하면 자식은 부모를 잃고 고아가 되어버린다. 그러하면 이 기능이 설정하였다고 하면 자식도 물론 삭제가 된다. 지금까지의 설명을 들으면 비슷하다거나 같은 설정이 있다. 바로 `CascadeType.REMOVE`이다.

 

이렇게 고아 객체와 삭제의 기능을 어떻게 설정하고 사용하는지에 대해 공부해 보았다.

'JPA' 카테고리의 다른 글

[JPA] 양방향 매핑과 연관관계  (0) 2024.08.09
[JPA] 영속성 컨텍스트란?  (0) 2024.03.10
[JPA] 1차 캐시란?  (1) 2024.03.05