[java] JPA OneToMany가 하위를 삭제하지 않음

@OneToMany부모와 자식 엔터티 간의 간단한 매핑에 문제가 있습니다. 자식 레코드는 컬렉션에서 제거해도 삭제되지 않습니다.

부모 :

@Entity
public class Parent {
    @Id
    @Column(name = "ID")
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
    private Set<Child> childs = new HashSet<Child>();

 ...
}

아이:

@Entity
public class Child {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="PARENTID", nullable = false)
    private Parent parent;

  ...
}

이제 childs Set에서 자식을 삭제하면 데이터베이스에서 삭제되지 않습니다. child.parent참조를 무효화하려고 시도했지만 작동하지 않았습니다.

엔티티는 웹 애플리케이션에서 사용되며 삭제는 Ajax 요청의 일부로 발생합니다. 저장 버튼을 눌렀을 때 삭제 된 자식 목록이 없으므로 암시 적으로 삭제할 수 없습니다.



답변

JPA의 동작이 정확합니다 ( 사양에 따라 의미 ). 객체가 OneToMany 컬렉션에서 제거 되었기 때문에 단순히 삭제되지 않습니다. 이를 수행하는 공급 업체별 확장이 있지만 기본 JPA는이를 지원하지 않습니다.

부분적으로 이것은 JPA가 콜렉션에서 제거 된 것을 삭제해야하는지 실제로 알지 못하기 때문입니다. 객체 모델링 용어에서 이는 컴포지션 과 “집계 * 의 차이 입니다.

에서 구성 , 자식 개체는 부모 없이는 존재가 없습니다. 전형적인 예는 집과 방 사이입니다. 집을 삭제하면 객실도갑니다.

집계 는 더 느슨한 종류의 연결이며 코스 및 학생에 의해 대표됩니다. 코스를 삭제해도 학생은 여전히 ​​존재합니다 (아마도 다른 코스에 있음).

따라서 공급 업체별 확장을 사용하여이 동작을 강제 실행하거나 (가능한 경우) 명시 적으로 자식을 삭제하고 부모의 컬렉션에서 제거해야합니다.

나는 알고있다 :


답변

클레 투스의 답변 외에도 2010 년 12 월 이후의 JPA 2.0orphanRemoval@OneToMany주석에 대한 속성을 소개합니다 . 자세한 내용은이 블로그 항목을 참조하십시오 .

스펙이 비교적 새롭기 때문에 모든 JPA 1 제공자가 최종 JPA 2 구현을 갖지는 않습니다. 예를 들어, Hibernate 3.5.0-Beta-2 릴리스 는 아직이 속성을 지원하지 않습니다.


답변

당신은 이것을 시도 할 수 있습니다 :

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true).


답변

설명했듯이 JPA로 원하는 것을 수행 할 수 없으므로 hibernate.cascade 주석을 사용하여 Parent 클래스의 관련 코드는 다음과 같습니다.

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.PERSIST,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();

부모도 삭제했기 때문에 ‘ALL’을 간단하게 사용할 수 없었습니다.


답변

여기서 캐스케이드는 제거와 관련하여 부모를 제거하면 자식이 제거됨을 의미합니다. 협회가 아닙니다. JPA 제공자로 Hibernate를 사용하는 경우, hibernate specific cascade를 사용하여이를 수행 할 수 있습니다 .


답변

당신은 이것을 시도 할 수 있습니다 :

@OneToOne(cascade = CascadeType.REFRESH) 

또는

@OneToMany(cascade = CascadeType.REFRESH)


답변

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

여기를 참조 하십시오 .