Apa arti dari CascadeType.ALL untuk asosiasi JPA @ManyToOne

210

Saya pikir saya salah memahami arti cascading dalam konteks suatu @ManyToOnehubungan.

Kasus:

public class User {

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

}

public class Address {

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

}

Apa arti dari cascade = CascadeType.ALL? Misalnya, jika saya menghapus alamat tertentu dari database, bagaimana fakta bahwa saya menambahkan cascade = CascadeType.ALLmemengaruhi data saya ( User, saya kira)?

fora
sumber

Jawaban:

360

Arti dari CascadeType.ALLadalah bahwa kegigihan akan menyebarkan (kaskade) semua EntityManageroperasi ( PERSIST, REMOVE, REFRESH, MERGE, DETACH) ke entitas terkait.

Tampaknya dalam kasus Anda adalah ide yang buruk, karena menghapus Addressakan menyebabkan penghapusan yang terkait User. Karena pengguna dapat memiliki beberapa alamat, alamat lainnya akan menjadi yatim piatu. Namun, kasus terbalik (anotasi User) akan masuk akal - jika alamat hanya milik satu pengguna, aman untuk menyebarkan penghapusan semua alamat milik pengguna jika pengguna ini dihapus.

BTW: Anda mungkin ingin menambahkan mappedBy="addressOwner"atribut Userke sinyal Anda ke penyedia ketekunan bahwa kolom gabungan harus dalam tabel ADDRESS.

kostja
sumber
55
+1 untuk penjelasan terbaik dan terpendek dari mappedBy yang pernah saya temui.
Ridcully
4
Bisa jadi baik untuk memiliki CascadeType.ALL di sisi @OneToMany.
mvmn
48

Lihat di sini untuk contoh dari dokumen OpenJPA. CascadeType.ALLberarti akan melakukan semua tindakan.

Mengutip:

CascadeType.PERSIST: Saat bertahan suatu entitas, juga bertahan entitas yang dimiliki di bidangnya. Kami menyarankan penerapan liberal aturan kaskade ini, karena jika EntityManager menemukan bidang yang mereferensikan entitas baru selama flush, dan bidang tidak menggunakan CascadeType.PERSIST, itu adalah kesalahan.

CascadeType.REMOVE: Saat menghapus entitas, ia juga menghapus entitas yang ada di bidang ini.

CascadeType.REFRESH: Saat menyegarkan entitas, juga menyegarkan entitas yang dimiliki di bidang ini.

CascadeType.MERGE: Saat menggabungkan status entitas, juga menggabungkan entitas yang dimiliki di bidang ini.

Sebastian

seba.wagner
sumber
4
Baru di JPA, informasi ini berguna tetapi bagaimana dengan Detach di sini?
Sarz
1
Dalam CascadeType.DETACH, saat melepaskan suatu entitas, mereka juga melepaskan entitas yang dimiliki oleh entitas induk.
Dorian Mejer
29

Seperti yang saya jelaskan di artikel ini dan dalam buku saya, High-Performance Java Persistence , Anda tidak harus menggunakan CascadeType.ALLpada @ManyToOnesejak transisi entitas negara harus merambat dari entitas Induk untuk yang anak, bukan sebaliknya.

The @ManyToOnesisi selalu asosiasi anak karena memetakan kolom kunci asing yang mendasari.

Oleh karena itu, Anda harus memindahkan CascadeType.ALLdari @ManyToOneasosiasi ke @OneToManysamping, yang juga harus menggunakan mappedByatribut karena itu adalah pemetaan hubungan tabel satu-ke-banyak yang paling efisien .

Vlad Mihalcea
sumber
18

Dari Spesifikasi EJB3.0 :

Penggunaan elemen penjelasan kaskade dapat digunakan untuk menyebarkan efek operasi ke entitas terkait. Fungsionalitas kaskade paling sering digunakan dalam hubungan orangtua-anak.

Jika X adalah entitas yang dikelola, operasi penghapusan menyebabkannya dihapus. Operasi penghapusan dibuatkan ke entitas yang dirujuk oleh X, jika hubungan dari X ke entitas lain ini dijelaskan dengan kaskade = HAPUS atau kaskade = SEMUA nilai elemen penjelasan.

Jadi singkatnya, hubungan entitas yang didefinisikan dengan CascadeType.Allakan memastikan bahwa semua peristiwa kegigihan seperti bertahan, menyegarkan, menggabungkan dan menghapus yang terjadi pada orang tua, akan diteruskan ke anak. Menentukan CascadeTypeopsi lain memberikan pengembang dengan tingkat kontrol yang lebih rinci tentang bagaimana asosiasi entitas menangani kegigihan.

Sebagai contoh jika saya memiliki buku objek yang berisi daftar halaman dan saya menambahkan objek halaman dalam daftar ini. Jika @OneToManyanotasi yang mendefinisikan hubungan antara Buku dan Halaman ditandai sebagai CascadeType.All, mempertahankan Buku akan menyebabkan Halaman juga tetap ada di database.

Kevin Bowersox
sumber
11

Di JPA 2.0 jika Anda ingin menghapus alamat jika Anda menghapusnya dari entitas Pengguna Anda dapat menambahkan orphanRemoval=true(bukan CascadeType.REMOVE) ke Anda @OneToMany.

Penjelasan lebih lanjut antara orphanRemoval=truedan CascadeType.REMOVEada di sini .

Emilien Brigand
sumber
4

Jika Anda hanya ingin menghapus alamat yang diberikan kepada pengguna dan tidak mempengaruhi kelas entitas Pengguna Anda harus mencoba sesuatu seperti itu:

@Entity
public class User {
   @OneToMany(mappedBy = "addressOwner", cascade = CascadeType.ALL)
   protected Set<Address> userAddresses = new HashSet<>();
}

@Entity 
public class Addresses {
   @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "user_id")
   protected User addressOwner;
}

Dengan cara ini Anda tidak perlu khawatir tentang menggunakan pengambilan dalam anotasi. Tapi ingat ketika menghapus Pengguna Anda juga akan menghapus alamat yang terhubung ke objek pengguna.

szachMati
sumber