2010-06-02 8 views
21

Ich versuche, die @OrderColumn Annotation mit Hibernate 3,5JPA 2.0 @OrderColumn Anmerkung in Hibernate 3.5

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
@OrderColumn(name = "pos") 
private List<Children> childrenCollection; 

zu verwenden, wenn das Abrufen von Daten, funktioniert alles einwandfrei. Aber ich kann es nicht veranlassen, Elemente in der Liste neu anzuordnen und den neuen Auftrag in der Datenbank zu speichern.

+0

Können Sie zeigen, wie Sie neu zu ordnen Ihre Liste und speichern zurück zur Datenbank ??? –

+0

Ich habe versucht, neue ArrayList und parent.setChildrenCollection (newList) Ich habe versucht Collections.sort auf abgerufene Liste. Ich habe auch versucht, null Elemente aus der Sammlung zu entfernen. Nichts ist passiert. Andere Änderungen in Eltern wurden in der Datenbank gespeichert, aber nichts passierte mit der Liste. –

+0

ist nicht Hibernate 3.5 für JPA 1.0 und @OrderColumn ist JPA 2.0 ?! –

Antwort

25

Die Kombination von @OneToMany (mappedBy = "...") und @OrderColumn wird von Hibernate nicht unterstützt. Diese JIRA Ausgabe verfolgt eine Anfrage eine offensichtliche Fehlermeldung zu werfen, wenn diese ungültige Kombination verwendet wird: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5390

Ich denke, dass dies nicht in erster Linie unterstützt wird, weil es ein ungeradees Beziehungsmuster ist. Die obigen Anmerkungen zeigen an, dass die "Eins" -Seite der Beziehung bestimmt, wie die Beziehung zur Datenbank geleert wird, aber die Reihenfolge/Position ist nur auf der "Viele" -Seite verfügbar, indem die Liste untersucht wird. Es macht mehr Sinn für die "viele" Seite, die Beziehung zu besitzen, da diese Seite sowohl die Mitgliedschaft als auch die Anordnung der Elemente kennt.

Die Hibernate Annotations Dokumente beschreiben diese Situation im Detail:

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype-indexbidir

Die Abhilfe ist das „mappedBy“ Attribut zu entfernen, die der Verband die Standard Join-Tabelle Strategie führen wird anstelle eines verwenden, Spalte auf der Zieltabelle. Sie können den Namen der Join-Tabelle mit der Annotation @JoinTable angeben.

Der Nettoeffekt dieser Änderung ist, dass die "viele" Seite der Beziehung jetzt bestimmt, wie die Beziehung beibehalten wird. Ihr Java-Code muss sicherstellen, dass die Liste korrekt aktualisiert wird, da Hibernate beim Löschen der Entitäten jetzt die "Eins" -Seite ignoriert.

Wenn Sie immer noch die „eine“ Seite zugänglich in Java haben wollen, wo es sich mit

@ManyToOne 
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false) 
+4

Es ist witzig, dass das "offizielle" Beispiel für explizite Indexspalten genau die Kombination '@OneToMany (mappedBy =" ... ")' + '@ OrderColumn' verwendet (siehe Beispiel 7.8 in http: //docs.jboss).org/hibernate/core/3.6/reference/de/html/collections.html # collections-indiziert) –

+2

Nach dieser Antwort wurde vereinbart, dass die Situation trotzdem unterstützt werden muss. Gail Badner: "Ich stimme zu, dass @OneToMany (mappedBy =" ... ") unterstützt werden sollte." –

+1

Gibt es einen anderen JPA-Provider (wie Eclipselink), der '@OneToMany (mappedBy =" ... ")' 'unterstützt? – deamon

3

Sie sollten versuchen, OrderColumn auf den Eigentümer des Vereins zu spezifizieren. Oder in Ihrem Mapping setzen Sie den Besitzer auf das Kind, der Besitzer sollte das Elternteil sein (in einer bidirektionalen Assoziation ist der Besitzer derjenige, der nicht das Schlüsselwort mappedBy hat, hier setzen Sie dieses Schlüsselwort auf die Klasse des Elternteils Sie meinen, dass die Klasse der Eltern nicht der Eigentümer ist)

In Ihrer untergeordneten Klasse sollten Sie das Schlüsselwort mappedBy auf der parentCollection haben. Aber nicht auf der ChildrenCollection.
Und in Ihrem Elternklasse sollten Sie die Anmerkung @JoinTable, so etwas wie dieses:

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
@OrderColumn(name = "pos") 
@JoinTable(name = "<NAME_OF_YOUR_TABLE>", joinColumns = @JoinColumn(<JOIN_COLUMNS_...>) 
private List<Children> childrenCollection; 
9

etwas tun:

@Entity 
class Parent { 

    @OneToMany 
    @OrderColumn(name = "pos") 
    List<Child> children; 
} 

@Entity 
class Child { 

    @ManyToOne 
    Parent parent; 
    @Column(name = "pos") 
    Integer index; 

    @PrePersist 
    @PreUpdate 
    private void prepareIndex() { 
     if (parent != null) { 
      index = parent.children.indexOf(this); 
     } 
    } 
} 
+2

Ich denke, in prepareIndex() sollte es geändert werden index = parent.children.indexOf (this); if (index == -1) index = parent.children.size(); – cn123h