Ich bin etwas verwirrt über das JPA 2.0- orphanRemoval
Attribut.
Ich denke, ich kann sehen, dass dies erforderlich ist, wenn ich die DB-Generierungstools meines JPA-Anbieters verwende, um die zugrunde liegende Datenbank-DDL zu erstellen, die eine ON DELETE CASCADE
Beziehung zu der jeweiligen Beziehung aufweist.
Wenn die Datenbank jedoch vorhanden ist und bereits eine ON DELETE CASCADE
Beziehung besteht, reicht dies nicht aus, um die Löschung entsprechend zu kaskadieren? Was macht der orphanRemoval
zusätzlich?
Prost
quelle
Ein Beispiel genommen Form hier :
Wenn ein
Employee
Entitätsobjekt entfernt wird, wird die Entfernungsoperation auf das referenzierteAddress
Entitätsobjekt kaskadiert . In dieser HinsichtorphanRemoval=true
undcascade=CascadeType.REMOVE
sind identisch, und wennorphanRemoval=true
angegeben,CascadeType.REMOVE
ist redundant.Der Unterschied zwischen den beiden Einstellungen besteht in der Reaktion auf das Trennen einer Beziehung. Zum Beispiel, wenn Sie das Adressfeld auf
null
oder auf ein anderesAddress
Objekt setzen.Wenn
orphanRemoval=true
angegeben, wird die getrennteAddress
Instanz automatisch entfernt. Dies ist nützlich, um abhängige Objekte (z. B.Address
) zu bereinigen, die ohne einen Verweis von einem Eigentümerobjekt (zEmployee
. B. ) nicht existieren sollten .Wenn nur
cascade=CascadeType.REMOVE
angegeben wird, wird keine automatische Aktion ausgeführt, da das Trennen einer Beziehung kein Entfernungsvorgang ist.Um zu vermeiden, dass Referenzen durch das Entfernen verwaister Objekte hängen bleiben, sollte diese Funktion nur für Felder aktiviert werden, die private, nicht gemeinsam genutzte abhängige Objekte enthalten.
Ich hoffe das macht es klarer.
quelle
Sobald Sie eine untergeordnete Entität aus der Sammlung entfernen, entfernen Sie diese untergeordnete Entität ebenfalls aus der Datenbank. orphanRemoval bedeutet auch, dass Sie die Eltern nicht wechseln können. Wenn es eine Abteilung mit Mitarbeitern gibt, haben Sie diesen Mitarbeiter beim Löschen / Festschreiben (je nachdem, was zuerst eintritt) versehentlich aus der Datenbank entfernt, sobald Sie diesen Mitarbeiter entfernt haben, um ihn in eine andere Abteilung zu verschieben. Die Moral besteht darin, orphanRemoval auf true zu setzen, solange Sie sicher sind, dass Kinder dieses Elternteils während ihrer gesamten Existenz nicht zu einem anderen Elternteil migrieren. Durch Aktivieren von orphanRemoval wird REMOVE automatisch zur Kaskadenliste hinzugefügt.
quelle
department.remove(emp);
anrufe, wird dieser Mitarbeiter aus der emp-Tabelle gelöscht, ohne überhauptcommit()
Die entsprechende JPA-Zuordnung für die DDL
ON DELETE CASCADE
lautetcascade=CascadeType.REMOVE
. Verwaiste Entfernung bedeutet, dass abhängige Entitäten entfernt werden, wenn die Beziehung zu ihrer "übergeordneten" Entität zerstört wird. Zum Beispiel, wenn ein Kind aus einer@OneToMany
Beziehung entfernt wird, ohne es explizit im Entitätsmanager zu entfernen.quelle
cascade=CascadeType.REMOVE
ist NICHT gleichbedeutend mitON DELETE CASCADE
. Ein wird im Anwendungscode entfernt und wirkt sich nicht auf DDL aus, andere werden in DB ausgeführt. Siehe stackoverflow.com/a/19696859/548473Der Unterschied ist:
- orphanRemoval = true: Die Entität "Child" wird entfernt, wenn nicht mehr darauf verwiesen wird (das übergeordnete Element wird möglicherweise nicht entfernt).
- CascadeType.REMOVE: Die Entität "Child" wird nur entfernt, wenn die Entität "Parent" entfernt wird.
quelle
Übergänge des Entitätsstatus
JPA übersetzt Entitätsstatusübergänge in SQL-Anweisungen wie INSERT, UPDATE oder DELETE.
Wenn Sie
persist
eine Entität sind, planen Sie, dass die INSERT-Anweisung ausgeführt wird, wenn sieEntityManager
automatisch oder manuell gelöscht wird.Wenn Sie
remove
eine Entität sind, planen Sie die DELETE-Anweisung, die ausgeführt wird, wenn der Persistenzkontext gelöscht wird.Übergänge von kaskadierenden Entitätszuständen
Mit JPA können Sie Entitätsstatusübergänge von übergeordneten Entitäten zu untergeordneten Entitäten weitergeben.
Wenn Sie also eine übergeordnete
Post
Entität haben, die mit der untergeordneten Entität@OneToMany
verknüpft istPostComment
:Die
comments
Sammlung in derPost
Entität wird wie folgt zugeordnet:CascadeType.ALL
Das
cascade
Attribut weist den JPA-Anbieter an, den Entitätsstatusübergang von der übergeordnetenPost
Entität an allePostComment
in dercomments
Auflistung enthaltenen Entitäten zu übergeben .Wenn Sie also die
Post
Entität entfernen :Der JPA-Anbieter entfernt zuerst die
PostComment
Entität. Wenn alle untergeordneten Entitäten gelöscht werden, wird auch diePost
Entität gelöscht :Waisenentfernung
Wenn Sie das
orphanRemoval
Attribut auf festlegentrue
, plant der JPA-Anbieter einenremove
Vorgang, wenn die untergeordnete Entität aus der Sammlung entfernt wird.In unserem Fall also
Der JPA-Anbieter wird den zugehörigen
post_comment
Datensatz entfernen, daPostComment
in dercomments
Sammlung nicht mehr auf die Entität verwiesen wird :AUF KASKADE LÖSCHEN
Das
ON DELETE CASCADE
ist auf FK-Ebene definiert:Wenn Sie dies tun, löschen Sie eine
post
Zeile:Alle zugeordneten
post_comment
Entitäten werden vom Datenbankmodul automatisch entfernt. Dies kann jedoch eine sehr gefährliche Operation sein, wenn Sie versehentlich eine Stammentität löschen.Fazit
Der Vorteil von JPA
cascade
undorphanRemoval
Optionen besteht darin, dass Sie auch von einer optimistischen Sperrung profitieren können , um verlorene Updates zu vermeiden .Wenn Sie den JPA-Kaskadenmechanismus verwenden, müssen Sie keine DDL-Ebene verwenden. Dies
ON DELETE CASCADE
kann eine sehr gefährliche Operation sein, wenn Sie eine Stammentität entfernen, die viele untergeordnete Entitäten auf mehreren Ebenen enthält.quelle
CascadeType
. Es ist ein komplementärer Mechanismus. Jetzt verwechseln Sie das Entfernen mit dem Fortbestehen. Beim Entfernen von Waisen geht es darum, nicht referenzierte Zuordnungen zu löschen, während beim Fortbestehen neue Entitäten gespeichert werden. Sie müssen den in der Antwort angegebenen Links folgen, um diese Konzepte besser zu verstehen.@GaryK Antwort ist absolut großartig, ich habe eine Stunde lang nach einer Erklärung suchen
orphanRemoval = true
vsCascadeType.REMOVE
und es hat mir geholfen , zu verstehen.Zusammenfassend: Funktioniert
orphanRemoval = true
identisch mitCascadeType.REMOVE
NUR WENN wir object (entityManager.delete(object)
) löschen und möchten, dass auch die untergeordneten Objekte entfernt werden.In einer völlig anderen Situation führt das Abrufen von Daten wie
List<Child> childs = object.getChilds()
und das anschließende Entfernen von child (entityManager.remove(childs.get(0)
) usingorphanRemoval=true
dazu, dass die entsprechende Entitätchilds.get(0)
aus der Datenbank gelöscht wird.quelle
Das Entfernen von Waisen hat im folgenden Szenario den gleichen Effekt wie ON DELETE CASCADE: - Nehmen wir an, wir haben eine einfache Beziehung zwischen der Schülerentität und einer Leitfadenentität, bei der viele Schüler demselben Leitfaden zugeordnet werden können, und in der Datenbank haben wir eine Fremdschlüsselbeziehung zwischen Student- und Guide-Tabelle, sodass die Student-Tabelle id_guide als FK hat.
// Die übergeordnete Entität
In diesem Szenario ist die Beziehung so, dass die Schülerentität der Eigentümer der Beziehung ist, und als solche müssen wir die Schülerentität speichern, um den gesamten Objektgraphen beizubehalten, z
Hier ordnen wir dieselbe Anleitung zwei verschiedenen Schülerobjekten zu. Da CASCADE.PERSIST verwendet wird, wird das Objektdiagramm wie folgt in der Datenbanktabelle gespeichert (in meinem Fall MySQL).
STUDENTentabelle: -
ID Name Dept Id_Guide
1 Roy ECE 1
2 Nick ECE 1
GUIDE Tabelle: -
ID NAME Gehalt
1 John $ 1500
und nun, wenn ich einen der Schüler entfernen möchte, mit
und wenn ein Schülerdatensatz entfernt wird, sollte auch der entsprechende Führungsdatensatz entfernt werden. Hier kommt das CASCADE.REMOVE-Attribut in der Schülerentität ins Bild und bewirkt, dass der Schüler mit der Kennung 1 sowie das entsprechende Leitobjekt (Kennung) entfernt werden 1). In diesem Beispiel gibt es jedoch ein weiteres Schülerobjekt, das demselben Leitfadendatensatz zugeordnet ist. Wenn wir das Attribut orphanRemoval = true in der Leitfadenentität nicht verwenden, funktioniert der obige Entfernungscode nicht.
quelle