[java] JPA에서 CascadeType.REMOVE와 orphanRemoval의 차이점은 무엇입니까?

차이점은 무엇입니까

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

이 예제는 Java EE Tutorial에서 가져온 것이지만 여전히 세부 사항을 이해하지 못합니다.



답변

에서 여기 : –

계단식 제거

참조 필드를 CascadeType.REMOVE (또는 REMOVE를 포함하는 CascadeType.ALL)로 표시하면 제거 작업이 해당 필드에서 참조하는 엔터티 개체에 자동으로 연결되어야 함을 나타냅니다 (여러 개체 개체는 컬렉션 필드에서 참조 할 수 있음).

@Entity
class Employee {
     :
    @OneToOne(cascade=CascadeType.REMOVE)
    private Address address;
     :
}

고아 제거

JPA 2는 @OneToOne 및 @OneToMany 주석의 orphanRemoval 요소를 사용하여 지정할 수있는보다 적극적인 추가 제거 계단식 모드를 지원합니다.

@Entity
class Employee {
     :
    @OneToOne(orphanRemoval=true)
    private Address address;
     :
}

차:-

두 설정의 차이점은 관계 연결 해제에 대한 응답입니다. 예를 들어 주소 필드를 null 또는 다른 주소 개체로 설정하는 경우입니다.

  • 경우 orphanRemoval = 사실 IS 지정한 연결이 끊긴 주소 인스턴스는 자동으로 제거됩니다. 이것은 소유자 개체 (예 : Employee)의 참조 없이는 존재하지 않아야하는 종속 개체 (예 : 주소)를 정리하는 데 유용합니다.
  • cascade = CascadeType.REMOVE 만 지정된 경우 관계 연결 해제는 제거
    작업 이 아니므로 자동 작업이 수행되지 않습니다 .


답변

CascadeType.REMOVE과 의 차이점을 쉽게 이해할 수있는 방법 orphanRemoval=true입니다.

고아 제거의 경우 :를 호출 setOrders(null)하면 관련 Order엔티티가 db에서 자동으로 제거됩니다.

계단식 제거의 경우 :를 호출 setOrders(null)하면 관련 Order엔티티가 db에서 자동으로 제거 되지 않습니다 .


답변

자식 엔터티와 부모 엔터티가 있다고 가정합니다. 부모는 여러 자녀를 가질 수 있습니다.

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

orphanRemoval은 ORM 개념이며 자식이 고아인지 여부를 알려줍니다. 또한 데이터베이스에서 제거해야합니다.

부모로부터 액세스 할 수없는 자식은 고아가됩니다. 예를 들어 Person 객체 세트를 제거하거나 (빈 세트로 설정) 새 세트로 바꾸면 부모는 더 이상 이전 세트의 자식에 액세스 할 수 없으며 자식은 고아가되어 자식이 데이터베이스에서도 제거되었습니다.

CascadeType.REMOVE는 데이터베이스 수준 개념이며 상위 항목이 제거되었는지 여부와 하위 테이블의 모든 관련 레코드를 제거해야 함을 알려줍니다.


답변

실제로 차이점은 데이터를 업데이트 (PATCH)하려고하는지 아니면 데이터를 완전히 대체 (PUT)하는지에 있습니다.

하자 당신이 삭제 말을 customer사용하는 것보다 cascade=REMOVE도 구성하고 유용한 것 같다 그 고객의 주문을 제거합니다.

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

이제 당신이 업데이트 가정 해 봅시다 customerorphanRemoval="true"그 이전의 모든 주문을 삭제하고 제공 한 사람과 그들을 대체합니다. ( PUT기준 REST API)

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

orphanRemoval오래된 명령이 없으면 보관됩니다. ( PATCH기준 REST API)


답변

이 질문은 매우 일반적이기 때문에이 답변은 제가 블로그에 작성한 이 기사를 기반으로 합니다 .

CascadeType.REMOVE

CascadeType.REMOVE명시 적으로 구성 할 수 있는 전략 :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

또는 CascadeType.ALL전략 에서 암시 적으로 상속 :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

remove상위 엔티티에서 하위 엔티티로 작업 을 전파 할 수 있습니다 .

따라서 컬렉션 Post과 함께 상위 항목을 가져오고 항목을 comments제거하면 post:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

Hibernate는 세 개의 delete 문을 실행할 것입니다.

DELETE FROM post_comment
WHERE id = 2

DELETE FROM post_comment
WHERE id = 3

DELETE FROM post
WHERE id = 1

전략으로 PostComment인해 하위 엔티티가 삭제되었으며 이는 하위 엔티티도 CascadeType.REMOVE제거 된 것처럼 작동했습니다.

고아 제거 전략

orphanRemoval속성을 통해 설정해야하는 고아 제거 전략 :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

컬렉션에서 자식 엔터티를 제거 할 때 자식 테이블 행을 제거 할 수 있습니다.

따라서 컬렉션과 Post함께 엔티티를 로드 하고 comments컬렉션에서 첫 번째 항목 PostComment을 제거하면 comments:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

Hibernate는 관련 post_comment테이블 행에 대해 DELETE 문을 실행할 것입니다 .

DELETE FROM post_comment
WHERE id = 2

이 주제에 대한 자세한 내용은 이 기사 도 확인하십시오 .


답변