2016-07-07 9 views
0

Ermöglicht Hibernate, die Reihenfolge der Ausführung untergeordneter Elemente zu definieren, die als Liste in einem POJO definiert sind. Angenommen, wir haben eine Klasse Parent, die mehrere untergeordnete Elemente enthält (Child1, Child2). Die Zuordnung zwischen Eltern und Kind ist OneToMany und sie sind als Liste definiert. Wir haben bidirektionale Beziehung zwischen Eltern-Kind. Es gibt auch eine ManyToOne-Beziehung zwischen Child1 und Child2. Child2 hat ManyToOne Beziehung mit Child1, d. H. Child2 enthält den Primärschlüssel Child1 als Fremdschlüssel Referenz und beide teilen OneToMany Beziehung mit Parent.Ermöglicht Hibernate, die Reihenfolge des Speicherns untergeordneter Elemente zu definieren

Nehmen wir an, dass wir alle mögliche Eltern-Kind-Beziehung zur Verfügung gestellt haben und jetzt rufen wir Merge-Methode der Hibernate-Sitzung. Das Problem, mit dem wir es hier zu tun haben, ist, dass die Assoziation zwischen Child1 und Child2 nicht verwaltet wird. Es gibt eine Hibernate-Ausnahme mit der Nachricht "Keine Zeile mit dem angegebenen Bezeichner existiert". Dieser Fehler ergibt sich aus dem Elternteil des Hibernate-Inserts, dann fügt er Child2 ein und fügt dann Child1 ein. Idealerweise sollte es Parent, Child1 und Child2 einfügen. So kann es die Verbindung zwischen Child1 und Child2 verwalten.

Idealerweise werden die Klassen so abgerufen, wie sie in der Sitzungsfabrik definiert wurden, oder sie werden in der Datei hibernate.cfg.xml definiert. Hier haben wir versucht, die Reihenfolge der Definition von Klassen in XML zu ändern. Aber es ergibt sich dasselbe.

Wir haben auch die Fremdschlüsselreferenz Child1 gelöscht, die Child2 von Datenbank zugeordnet ist. Hibernate verwaltet die Beziehung jedoch automatisch, so dass sie nicht funktioniert.

Es gibt nur eine Anforderung an den Auftrag der Kinder in Parent Klasse

bitte die Vorschläge/Lösung so schnell wie möglich

Code Snippet liefert definierte Wechsel:

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

Das Problem IMHO ist die Merge-Methode. HIbernate funktioniert nicht so gut, wenn Sie Merge verwenden. Hibernate funktioniert nicht wirklich gut im Umgang mit losgelösten Entitäten. Ich meine, es hat dieses Feature und es kann in vielen einfacheren Situationen helfen. Aber es rockt nicht wirklich. Wir hatten dieses Problem auch in unserem Projekt. Dann haben wir alles auf DTOs umgestellt. Alles funktioniert jetzt viel reibungsloser. –

+0

Ja meiner Meinung nach DTO wäre auch nützlich. Ihre Kernlogik sollte die Domäne darstellen, und wenn der Client, d. H. Das Web, einige Daten benötigt, die in der Ansicht im Vergleich zur Domäne ruhig sind, dann verwenden Sie das Datenübertragungsobjekt, um mit der Situation umzugehen. –

Antwort

0

Wie gesagt in mein Kommentar, mit merge ist nicht ideal.

Wie auch immer, könnten Sie umgehen, indem Sie einige Kinder zuerst zusammenführen.

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

By the way, müssen Sie nur merge, wenn das Objekt bereits in der Sitzung ist. Wenn es nicht garantiert ist, verwenden Sie einfach saveOrUpdate.

session.saveOrUpdate(parent); 
+0

Ich denke du meinst 'saveOrUpdate()' –

+0

Ja, danke, habe es behoben. –