2016-07-07 3 views
0

최대 절전 모드는 POJO에서 List로 정의 된 자식 요소의 실행 순서를 정의 할 수 있는가? 여러 개의 자식 (Child1, Child2)을 포함하는 하나의 Parent 클래스가 있다고 가정합니다. 부모와 자식 간의 연결은 OneToMany이며 목록으로 정의됩니다. 부모 - 자식간에 양방향 관계가 있습니다. Child1Child2 사이에는 ManyToOne 관계가 있습니다. Child2Child1과 ManyToOne 관계가 있습니다. 즉, 은 기본 키가 Child1이고 외래 키 참조는 모두 Parent 인 OneToMany 관계를 공유합니다.hibernate는 자식 요소 저장 순서를 정의 할 수 있는가

우리는 가능한 모든 부모 - 자식 관계를 제공한다고 가정하고 이제 우리는 최대 절전 세션의 병합 메서드를 호출하고 있습니다. 여기서 우리가 직면 한 문제는 Child1Child2 사이의 연결이 관리되지 않는다는 것입니다. "지정된 식별자가있는 행이 없습니다"라는 메시지와 함께 최대 절전 예외를 제공합니다. 이 오류는 최대 절전 모드 삽입 부모 때문에 발생하고 Child2을 삽입 한 다음 Child1을 삽입합니다. 이상적으로 그것은 Parent, Child1Child2을 삽입해야합니다. 따라서 Child1Child2 사이의 연결을 관리 할 수 ​​있습니다.

이상적으로 클래스는 세션 팩토리에 정의 된대로 페치되거나 hibernate.cfg.xml 파일에 정의됩니다. 여기에서는 XML로 클래스를 정의하는 순서를 변경하려고 시도했습니다. 그러나 결과는 같습니다.

우리는 과 관련된 foreign key reference도 데이터베이스에서 Child1을 삭제했습니다. 하지만 최대 절전 모드로 자동으로 관계를 관리하므로 문제가 해결되지 않습니다.

public class Parent{ 
    private List<Child1> child1; 
    private List<Child2> child2; 

    public Parent(){ 
     child1 = Collectionz.newArrayList(); 
     child2 = Collectionz.newArrayList(); 
    } 


    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true) 
    @Fetch(FetchMode.SUBSELECT) 
    public List<Child1> getChild1() { 
     return child1; 
    } 

    public void setChild1(List<Child1> child1) { 
     this.child1 = child1; 
    } 


    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true) 
    @Fetch(FetchMode.SUBSELECT) 
    public List<Child2> getChild2() { 
     return child2; 
    } 

    public void setChildren2(List<Child2> child2) { 
     this.child2 = child2; 
    } 

} 

public class Child1{ 
    private Parent parent; 
    private Set<Child2> child2; 

    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="PARENT_ID") 
    public PkgData getParent() { 
     return parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 


    @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY,mappedBy="child1") 
    @Fetch(FetchMode.SUBSELECT) 
    public Set<Child2> getChild2() { 
     return child2; 
    } 
    public void setChild2(Set<Child2> child2) { 
     this.child2 = child2; 
    } 

} 


public class child2{ 
    private Parent parent; 
    private Child1 child1; 


    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="PARENT_ID") 
    public PkgData getParent() { 
     return parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 


    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="CHILD_1_ID") 
    public Child1 getChild1() { 
     return child1; 
    } 

    public void setChild1(Child1 child1) { 
     this.child1 = child1; 
    } 
} 
+0

문제점 IMHO는 병합 방법입니다. 병합을 사용할 때 HIbernate가 잘 작동하지 않습니다. Hibernate는 분리 된 엔티티들을 다룰 때 실제로 그렇게 잘 작동하지 않는다. 내 말은,이 기능이 있으며 많은 간단한 상황에서 도움이 될 수 있습니다. 그러나 그것은 정말로 흔들리지 않습니다. 우리는 프로젝트에서도이 문제를 가지고있었습니다. 그런 다음 모든 것을 DTO 사용으로 변경했습니다. 이제는 모든 것이 훨씬 부드럽게 작동합니다. –

+0

제 생각에는 DTO가 유용 할 것입니다. 핵심 로직이 도메인을 나타내야하고 클라이언트 즉 웹이 도메인과 비교하여보기가 다른 일부 데이터를 필요로하는 경우 데이터 전송 객체를 사용하여 상황을 처리합니다. –

답변

0

내가에서 말했듯이 :

빨리

코드 조각 Parent 클래스 친절

에 정의 된 어린이의 삽입 순서 제안/솔루션을 제공을 변경하는 단 하나 개의 요구 사항이 내 코멘트는 merge을 사용하는 것이 이상적이지 않습니다.

어쨌든 일부 어린이를 먼저 병합하여이 문제를 해결할 수 있습니다. 객체가 세션에 이미있는 경우

그런데
// sorry if this is not correct java, I'm a C# programmer 
foreach(Child2 child2 in parent.Children2) 
{ 
    session.merge(child2); 
} 
session.merge(parent); 

merge이 필요합니다. 그렇지 않을 경우에는 saveOrUpdate을 사용하십시오.

session.saveOrUpdate(parent); 
+0

'saveOrUpdate()'를 의미하는 것 같아요 –

+0

네, 고맙습니다. –