Ja, das ist möglich. Dies ist ein Spezialfall der bidirektionalen Standard @ManyToOne
/ @OneToMany
Beziehung. Es ist etwas Besonderes, weil die Entität an jedem Ende der Beziehung dieselbe ist. Der allgemeine Fall ist in Abschnitt 2.10.2 der JPA 2.0-Spezifikation beschrieben .
Hier ist ein Beispiel. Erstens die Entitätsklasse A
:
@Entity
public class A implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@ManyToOne
private A parent;
@OneToMany(mappedBy="parent")
private Collection<A> children;
// Getters, Setters, serialVersionUID, etc...
}
Hier ist eine grobe main()
Methode, die drei solcher Entitäten beibehält:
public static void main(String[] args) {
EntityManager em = ... // from EntityManagerFactory, injection, etc.
em.getTransaction().begin();
A parent = new A();
A son = new A();
A daughter = new A();
son.setParent(parent);
daughter.setParent(parent);
parent.setChildren(Arrays.asList(son, daughter));
em.persist(parent);
em.persist(son);
em.persist(daughter);
em.getTransaction().commit();
}
In diesem Fall müssen alle drei Entitätsinstanzen vor dem Festschreiben der Transaktion beibehalten werden. Wenn ich eine der Entitäten im Diagramm der Eltern-Kind-Beziehungen nicht beibehalten kann, wird eine Ausnahme ausgelöst commit()
. Bei Eclipselink wird RollbackException
die Inkonsistenz detailliert beschrieben.
Dieses Verhalten kann über das cascade
Attribut A
ons @OneToMany
und @ManyToOne
Anmerkungen konfiguriert werden . Wenn ich beispielsweise cascade=CascadeType.ALL
beide Anmerkungen festlege , kann ich eine der Entitäten sicher beibehalten und die anderen ignorieren. Angenommen, ich habe parent
meine Transaktion fortgesetzt . Die JPA-Implementierung durchläuft parent
die children
Eigenschaft, da sie mit gekennzeichnet ist CascadeType.ALL
. Die JPA-Implementierung findet son
und daughter
dort. Es bleiben dann beide Kinder in meinem Namen bestehen, obwohl ich es nicht ausdrücklich angefordert habe.
Noch eine Anmerkung. Es liegt immer in der Verantwortung des Programmierers, beide Seiten einer bidirektionalen Beziehung zu aktualisieren. Mit anderen Worten, wenn ich einem Elternteil ein Kind hinzufüge, muss ich die Eltern-Eigenschaft des Kindes entsprechend aktualisieren. Das Aktualisieren nur einer Seite einer bidirektionalen Beziehung ist unter JPA ein Fehler. Aktualisieren Sie immer beide Seiten der Beziehung. Dies ist eindeutig auf Seite 42 der JPA 2.0-Spezifikation geschrieben:
Beachten Sie, dass die Anwendung für die Aufrechterhaltung der Konsistenz von Laufzeitbeziehungen verantwortlich ist, z. B. um sicherzustellen, dass die "eine" und die "viele" Seite einer bidirektionalen Beziehung miteinander konsistent sind, wenn die Anwendung die Beziehung zur Laufzeit aktualisiert .
Für mich bestand der Trick darin, eine Viele-zu-Viele-Beziehung zu verwenden. Angenommen, Ihre Entität A ist eine Abteilung, die Unterteilungen haben kann. Dann (Überspringen irrelevanter Details):
Da ich eine umfangreiche Geschäftslogik in Bezug auf die hierarchische Struktur hatte und JPA (basierend auf dem relationalen Modell) sehr schwach ist, um dies zu unterstützen, habe ich den
IHierarchyElement
Listener für Schnittstellen und Entitäten eingeführtHierarchyListener
:quelle
Top
handelt sich um eine Beziehung. Seite 93 der JPA 2.0-Spezifikation, Entitätslistener und Rückrufmethoden: "Im Allgemeinen sollte die Lebenszyklusmethode einer tragbaren Anwendung keine EntityManager- oder Abfragevorgänge aufrufen, nicht auf andere Entitätsinstanzen zugreifen oder Beziehungen ändern." Richtig? Lass es mich wissen, wenn ich weg bin.