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.

Paul Whelan
quelle

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)
Varun Mehta
quelle
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.

Kango_V
quelle
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                                               
╚═════════════╩═════════════════════╩═════════════════════╝
Sergii Shevchyk
quelle
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;
Reshma
quelle
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.

Valéry Stroeder
quelle
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.

Bevor
quelle
2

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

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

Kohan95
quelle
1

Für die Datensätze war es in OpenJPA vor JPA2 @ElementDependant.

Simone Gianni
quelle
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

Vipin Chauhan
quelle
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") private Child child;
Vipin Chauhan