JPA CascadeType.ALL löscht keine Waisenkinder


132

Ich habe Probleme beim Löschen verwaister Knoten mithilfe von JPA mit der folgenden Zuordnung

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

Ich habe das Problem mit den verwaisten Rollen, die in der Datenbank hängen.

Ich kann das Annotation org.hibernate.annotations.CascadeHibernate-spezifische Tag verwenden, möchte meine Lösung aber natürlich nicht in eine Hibernate-Implementierung einbinden.

EDIT : Es scheint, dass JPA 2.0 dies unterstützen wird.

Antworten:


164

Wenn Sie es mit Hibernate verwenden, müssen Sie die Annotation explizit definieren CascadeType.DELETE_ORPHAN, die in Verbindung mit JPA verwendet werden kann CascadeType.ALL.

Wenn Sie den Ruhezustand nicht verwenden möchten, müssen Sie zuerst explizit die untergeordneten Elemente und dann den Hauptdatensatz löschen, um verwaiste Datensätze zu vermeiden.

Ausführungssequenz

  1. Holen Sie sich die zu löschende Hauptzeile
  2. untergeordnete Elemente abrufen
  3. Löschen Sie alle untergeordneten Elemente
  4. Hauptzeile löschen
  5. Sitzung schließen

Mit JPA 2.0 können Sie jetzt die Option orphanRemoval = true verwenden

@OneToMany(mappedBy="foo", orphanRemoval=true)

3
Vielen Dank, dass ich diesen Weg gegangen bin. Ich denke, dies ist ein bisschen zu viel für die JPA-Spezifikation.
Paul Whelan

13
Der JPA 2.0-Standard hat jetzt deleteOrphan als Attribut für @OneToMany. Wenn Sie den neuesten Ruhezustand verwenden, können Sie @OneToMany (..., deleteOrphan = true)
ausführen

Was ist die Ausführungsreihenfolge, wenn ich nur untergeordnete Elemente aktualisiere? Werden verwaiste Datensätze gelöscht?
jAckOdE

113

Wenn Sie JPA 2.0 verwenden, können Sie jetzt das orphanRemoval=trueAttribut der @xxxToManyAnmerkung verwenden, um Waisen zu entfernen.

Eigentlich wurde CascadeType.DELETE_ORPHANin 3.5.2-Final veraltet.


6
Eigentlich denke ich, dass orphanRemoval = true etwas anderes bedeutet, dh ein Objekt löschen, wenn ich es aus der Sammlung seiner Eltern entferne. Siehe download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

Bitte g über Archies Link.
Jigar Shah

4
orphanRemoval = true funktioniert auch nicht. Es muss auf die alte Art gemacht werden.
Joe Almore

45
╔═════════════╦═════════════════════╦═════════════════════╗
   Action      orphanRemoval=true    CascadeType.ALL   
╠═════════════╬═════════════════════╬═════════════════════╣
   delete         deletes parent      deletes parent   
   parent         and orphans         and orphans      
╠═════════════╬═════════════════════╬═════════════════════╣
   change                                              
  children      deletes orphans         nothing        
    list                                               
╚═════════════╩═════════════════════╩═════════════════════╝

1
Was passiert, wenn ich cascade = CascadeType.ALL, orphanRemoval = falseden Elternteil habe und lösche? Wird es Kinder löschen, obwohl ich ausdrücklich gesagt habe, dass ich es NICHT tun soll?
izogfif


7

Sie können @PrivateOwned verwenden, um Waisenkinder zu löschen, z

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;

5
Dank @reshma sollte angemerkt werden, dass @PrivateOwned eine Eclipselink-JPA-Erweiterung ist.
Paul Whelan

5

Ich finde nur diese Lösung, aber in meinem Fall funktioniert sie nicht:

@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 

orphanRemoval = true hat keine Auswirkung.


1
Ich musste reinigen und bauen, bevor die Änderung in Kraft trat.
Maralbjo

Wow, ich habe eine Stunde lang gesucht, warum das Hinzufügen von CascadeType.ALL zu meinem ManyToOne keine kaskadierenden Löschvorgänge war. Gereinigt und gebaut und es funktioniert. Danke @maralbjo.
Andrew Mairose


2

Ich hatte das gleiche Problem und fragte mich, warum diese Bedingung die Waisen nicht löschte. Die Liste der Gerichte wurde im Ruhezustand (5.0.3.Final) nicht gelöscht, als ich eine benannte Löschabfrage ausführte:

@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();

Dann fiel mir ein, dass ich keine benannte Löschabfrage verwenden darf , sondern den EntityManager. Da ich die EntityManager.find(...)Methode verwendet habe, um die Entität abzurufen und dann EntityManager.remove(...)zu löschen, wurden auch die Gerichte gelöscht.


2

Einfach @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true).

Entfernen Sie targetEntity = MyClass.class , es funktioniert hervorragend.



0

Ich habe eine Eins-zu-Eins-Zuordnung verwendet, aber das Kind wurde nicht gelöscht. JPA hat eine Verletzung des Fremdschlüssels verursacht

Nach der Verwendung von orphanRemoval = true wurde das Problem behoben


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") private Child child;
Vipin Chauhan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.