2012-10-23 12 views
132

Ich glaube, ich vermisse die Bedeutung der Kaskadierung im Kontext der @ManyToOne Beziehung verstanden.JPA @ManyToOne mit CascadeType.ALL

Der Fall:

public class User { 

    @OneToMany(fetch = FetchType.EAGER) 
    protected Set<Address> userAddresses; 

} 

public class Address { 

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    protected User addressOwner; 

} 

Was die Bedeutung des cascade = CascadeType.ALL ist? Zum Beispiel, wenn ich eine bestimmte Adresse aus der Datenbank lösche, wie wirkt sich die Tatsache, dass ich die cascade = CascadeType.ALL hinzugefügt habe, auf meine Daten aus (der Benutzer denke ich)?

Antwort

230

Die Bedeutung von CascadeType.ALL ist, dass die Persistenz alle EntityManager Operationen (PERSIST, REMOVE, REFRESH, MERGE, DETACH) an die entsprechenden Entitäten weiterleitet (kaskadiert).

Es scheint in Ihrem Fall, eine schlechte Idee zu sein, als das Entfernen einer Address würde dazu führen, dass die damit verbundenen User entfernt werden. Da ein Benutzer mehrere Adressen haben kann, würden die anderen Adressen zu Waisen werden. Der umgekehrte Fall (Annotation der User) wäre jedoch sinnvoll - wenn eine Adresse nur einem einzelnen Benutzer gehört, ist es sicher, die Entfernung aller Adressen eines Benutzers zu propagieren, wenn dieser Benutzer gelöscht wird.

BTW: Vielleicht möchten Sie ein mappedBy="addressOwner" Attribut zu Ihrem User hinzufügen, um dem Persistenzanbieter zu signalisieren, dass die Join-Spalte in der ADDRESS-Tabelle sein sollte.

+27

+1 für die beste und kürzeste Erklärung von mappedBy, die ich je gesehen habe. – Ridcully

+3

Es könnte aber gut sein CascadeType.ALL auf @ OneToMany Seite zu haben. – mvmn

33

See here für ein Beispiel aus den OpenJPA-Dokumenten. CascadeType.ALL bedeutet, dass es alle Aktionen ausführt.

Zitat:

CascadeType.PERSIST: Wenn ein Unternehmen persistierenden, besteht auch die in diesem Bereich gehalten Einheiten. Wir empfehlen eine liberale Anwendung dieser Kaskadenregel, denn wenn der EntityManager ein Feld findet, das während des Flushings auf eine neue Entität verweist und das Feld nicht CascadeType.PERSIST verwendet, ist dies ein Fehler.

CascadeType.REMOVE: Löschen Sie beim Löschen einer Entität auch die in diesem Feld enthaltenen Entitäten.

CascadeType.REFRESH: Aktualisieren Sie beim Aktualisieren einer Entität auch die in diesem Feld enthaltenen Entitäten.

CascadeType.MERGE: Beim Zusammenführen des Entitätsstatus werden auch die in diesem Feld enthaltenen Entitäten zusammengeführt.

Sebastian

+3

Neu in JPA, diese Information ist nützlich, aber was ist los hier? – Sarz

+1

In CascadeType.DETACH lösen Sie beim Trennen einer Entität auch die Entitäten, die von der übergeordneten Entität gehalten werden. –

15

From the EJB3.0 Specification:

Verwendung der Kaskade Annotation Element kann die Wirkung einer Operation zugeordnet Entitäten propagieren verwendet werden. Die Kaskadierung wird am häufigsten in Parent-Child-Beziehungen verwendet.

Wenn X eine verwaltete Entität ist, wird sie durch den Entfernungsvorgang entfernt. Die Operation zum Entfernen wird an die Entitäten kaskadiert, die mit X, referenziert werden, wenn die Beziehungen von X zu diesen anderen Entitäten mit dem Wert des Annotationselements cascade = REMOVE oder cascade = ALL gekennzeichnet sind.

Also kurz gesagt, mit CascadeType.All definiert Entitätsbeziehungen wird sichergestellt, dass alle Ausdauer Ereignisse wie beharren, erfrischen, fusionieren und entfernen, die auf dem Eltern auftreten, wird das Kind übertragen werden. Das Definieren anderer CascadeType Optionen bietet dem Entwickler eine detailliertere Kontrolle darüber, wie die Entitätsassoziation die Persistenz behandelt.

Zum Beispiel, wenn ich ein Objekt hatte Buch, das eine Liste von Seiten enthielt und ich ein Seitenobjekt innerhalb dieser Liste hinzufügen. Wenn die Annotation @OneToMany, die die Verknüpfung zwischen Buch und Seite definiert, als CascadeType.All markiert ist, würde das Bleiben der Seite dazu führen, dass die Seite auch in der Datenbank beibehalten wird.

8

Wenn Sie in JPA 2.0 eine Adresse löschen möchten, wenn Sie sie aus einer Benutzereinheit entfernt haben, können Sie orphanRemoval=true (anstelle von CascadeType.REMOVE) zu Ihrer @OneToMany hinzufügen.

Weitere Erklärungen zwischen und CascadeType.REMOVE sind here.

6

Wie ich in this article und in meinem Buch erklärt, High-Performance Java Persistence, sollten Sie nie CascadeType.ALL auf @ManyToOne seit entity state transitions verwenden sollten von Eltern Entitäten Kind diejenigen propagieren.

Die Seite @ManyToOne ist immer die Child-Assoziation, da sie den zugrunde liegenden FK zuordnen sollte.

Daher bewegen sich die CascadeType.ALL vom @ManyToOne Assoziation zum @OneToMany, die das mappedBy Attribut verwenden sollte, da es the most efficient one-to-many mapping ist. `

Verwandte Themen