JPA CascadeType.ALL tidak menghapus anak yatim

132

Saya mengalami masalah menghapus node yatim menggunakan JPA dengan pemetaan berikut

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

Saya mengalami masalah peran yatim di sekitar basis data.

Saya dapat menggunakan org.hibernate.annotations.Cascadetag spesifik Hibernate anotasi tapi jelas saya tidak ingin mengikat solusi saya ke dalam implementasi Hibernate.

EDIT : Sepertinya JPA 2.0 akan menyertakan dukungan untuk ini.

Paul Whelan
sumber

Jawaban:

164

Jika Anda menggunakannya dengan Hibernate, Anda harus secara eksplisit mendefinisikan anotasi CascadeType.DELETE_ORPHAN, yang dapat digunakan bersama dengan JPA CascadeType.ALL.

Jika Anda tidak berencana untuk menggunakan Hibernate, Anda harus terlebih dahulu menghapus elemen anak dan kemudian menghapus catatan utama untuk menghindari catatan anak yatim.

urutan eksekusi

  1. ambil baris utama untuk dihapus
  2. ambil elemen anak
  3. hapus semua elemen anak
  4. hapus baris utama
  5. sesi tutup

Dengan JPA 2.0, Anda sekarang dapat menggunakan opsi orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)
Varun Mehta
sumber
3
terima kasih saya akhirnya melalui rute ini, saya pikir ini sedikit oversite untuk spesifikasi JPA.
Paul Whelan
13
Standar JPA 2.0 sekarang memiliki deleteOrphan sebagai atribut untuk @OneToMany. Jika Anda menggunakan hibernate terbaru, Anda dapat melakukan @OneToMany (..., deleteOrphan = true)
jomohke
apa urutan eksekusi ketika saya baru saja memperbarui elemen-anak? akankah catatan anak yatim dihapus?
jAckOdE
113

Jika Anda menggunakan JPA 2.0, sekarang Anda dapat menggunakan orphanRemoval=trueatribut @xxxToManyanotasi untuk menghapus anak yatim.

Sebenarnya, CascadeType.DELETE_ORPHANsudah usang di 3.5.2-Final.

Kango_V
sumber
6
Sebenarnya saya pikir orphanRemoval = true berarti sesuatu yang lain, yaitu, menghapus objek ketika saya menghapusnya dari koleksi orang tuanya. Lihat download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie
Silakan g melalui tautan Archie.
Jigar Shah
4
orphanRemoval = true juga tidak berfungsi. Itu harus dilakukan dengan cara lama.
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
sumber
1
Apa yang terjadi jika saya memiliki cascade = CascadeType.ALL, orphanRemoval = falsedan menghapus induknya? Apakah ini akan menghapus anak-anak, meskipun saya sudah secara khusus menyuruh TIDAK melakukannya?
izogfif
7

Anda dapat menggunakan @PrivateOwned untuk menghapus anak yatim misalnya

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;
reshma
sumber
5
Terima kasih @reshma, perlu dicatat @PrivateOwned adalah ekstensi JPA eclipselink.
Paul Whelan
5

Saya hanya menemukan solusi ini tetapi dalam kasus saya itu tidak berhasil:

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

orphanRemoval = true tidak berpengaruh.

Valéry Stroeder
sumber
1
Saya perlu membersihkan dan membangun sebelum perubahan mulai berlaku.
maralbjo
Wow, saya sudah mencari satu jam mengapa menambahkan CascadeType.ALL di ManyToOne saya tidak menghapus cascading. Dibersihkan dan dibangun dan berfungsi. Terima kasih @maralbjo.
Andrew Mairose
2

Saya memiliki masalah yang sama dan saya bertanya-tanya mengapa kondisi di bawah ini tidak menghapus anak yatim. Daftar hidangan tidak dihapus di Hibernate (5.0.3.Final) ketika saya menjalankan permintaan penghapusan bernama:

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

Lalu saya ingat bahwa saya tidak boleh menggunakan query delete bernama , tetapi EntityManager. Saat saya menggunakan EntityManager.find(...)metode untuk mengambil entitas dan kemudian EntityManager.remove(...)menghapusnya, piring juga dihapus.

Bevor
sumber
2

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

Hapus targetEntity = MyClass.class , ini berfungsi dengan baik.

Kohan95
sumber
1

Sebagai catatan, di OpenJPA sebelum JPA2 itu adalah @ElementDependant.

Simone Gianni
sumber
0

Saya menggunakan pemetaan satu ke satu, tetapi anak tidak dihapus JPA memberikan pelanggaran kunci asing

Setelah menggunakan orphanRemoval = true, masalah terselesaikan

vipin chauhan
sumber
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") pribadi Anak anak;
vipin chauhan