2016-07-07 4 views
0

hibernateは、POJOでListとして定義された子要素の実行順序を定義できますか? 複数の子を含む1つのParentクラスがあるとします(Child1Child2)。親と子の関連付けはOneToManyであり、リストとして定義されています。 親子の間に双方向の関係があります。 Child1Child2の間にManyToOne関係もあります。 Child2は、Child1とManyToOne関係を持ちます。つまり、は、外部キー参照としてChild1の主キーを含み、両方ともParentとOneToMany関係を共有します。hibernateは子要素の保存順序を定義することができます

私たちはすべての親子関係を提供していると仮定して、今度は、hibernate sessionのmergeメソッドを呼び出しています。私たちがここで直面している問題は、Child1Child2の間の関連付けが管理されていないことです。これは、 "指定された識別子の行がありません"というメッセージとともに、休止状態の例外を出します。このエラーは、休止状態の挿入親のために導出され、Child2を挿入してからChild1を挿入します。理想的には、Parent,Child1およびChild2を挿入する必要があります。したがって、Child1Child2の間の関連付けを管理できます。

理想的には、クラスはセッションファクトリで定義されたとおりにフェッチされるか、hibernate.cfg.xmlファイルで定義されます。ここでは、XMLでクラスを定義する順序を変更しようとしました。しかし、それは同じ結果をもたらします。

さらに、に関連付けられた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

問題は、マージメソッドです。マージを使用すると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

はい、ありがとう、それを修正しました。 –

関連する問題