JPA CascadeType.ALL ไม่ได้ลบเด็กกำพร้า


136

ฉันมีปัญหาในการลบโหนด orphan โดยใช้ JPA ด้วยการแมปต่อไปนี้

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

ฉันมีปัญหาของบทบาทที่ถูกทอดทิ้งซึ่งห้อยอยู่รอบ ๆ ฐานข้อมูล

ฉันสามารถใช้org.hibernate.annotations.Cascadeแท็กเฉพาะไฮเบอร์เนตคำอธิบายประกอบได้ แต่เห็นได้ชัดว่าฉันไม่ต้องการผูกโซลูชันของฉันเข้ากับการใช้งานไฮเบอร์เนต

แก้ไข : ดูเหมือนว่า JPA 2.0 จะรองรับสิ่งนี้ด้วย

คำตอบ:


164

หากคุณใช้กับ Hibernate คุณจะต้องกำหนดคำอธิบายประกอบอย่างชัดเจนCascadeType.DELETE_ORPHANซึ่งสามารถใช้ร่วมกับ JPA CascadeType.ALLได้

หากคุณไม่ได้วางแผนที่จะใช้ Hibernate คุณจะต้องลบองค์ประกอบลูกอย่างชัดเจนก่อนจากนั้นจึงลบระเบียนหลักเพื่อหลีกเลี่ยงระเบียนที่ไม่มีเด็ก

ลำดับการดำเนินการ

  1. เรียกแถวหลักที่จะลบ
  2. ดึงองค์ประกอบเด็ก
  3. ลบองค์ประกอบลูกทั้งหมด
  4. ลบแถวหลัก
  5. ปิดเซสชัน

ด้วย JPA 2.0 ตอนนี้คุณสามารถใช้ตัวเลือกorphanRemoval = true

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

3
ขอบคุณที่ฉันลงเอยด้วยการไปเส้นทางนี้ฉันคิดว่านี่เป็นการเกินขอบเขตสำหรับข้อมูลจำเพาะของ JPA
Paul Whelan

13
ตอนนี้มาตรฐาน JPA 2.0 มี deleteOrphan เป็นแอตทริบิวต์ของ @OneToMany หากคุณใช้ไฮเบอร์เนตล่าสุดคุณสามารถทำได้ @OneToMany (... , deleteOrphan = true)
jomohke

ลำดับการดำเนินการคืออะไรเมื่อฉันเพิ่งอัปเดตองค์ประกอบลูก ระเบียนเด็กกำพร้าจะถูกลบหรือไม่
jAckOdE

113

หากคุณใช้ JPA 2.0 ตอนนี้คุณสามารถใช้orphanRemoval=trueแอตทริบิวต์ของ@xxxToManyคำอธิบายประกอบเพื่อลบเด็กกำพร้าได้

จริงๆแล้วCascadeType.DELETE_ORPHANได้เลิกใช้งานไปแล้วใน 3.5.2-Final


6
จริงๆแล้วฉันคิดว่า orphanRemoval = true หมายถึงอย่างอื่นเช่นลบวัตถุเมื่อฉันลบออกจากคอลเล็กชันของผู้ปกครอง ดูdownload.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

กรุณาส่งลิงก์ของ Archie
Jigar Shah

4
orphanRemoval = trueก็ใช้ไม่ได้เช่นกัน มันต้องทำแบบเก่า
Joe Almore

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

1
จะเกิดอะไรขึ้นถ้าฉันมีcascade = CascadeType.ALL, orphanRemoval = falseและลบผู้ปกครอง จะลบเด็กแม้ว่าฉันจะบอกว่าไม่ให้ทำโดยเฉพาะ?
izogfif


7

คุณสามารถใช้ @PrivateOwned เพื่อลบเด็กกำพร้าเช่น

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

5
ขอบคุณ @reshma ควรสังเกต @PrivateOwned เป็นส่วนขยาย eclipselink JPA
Paul Whelan

6

ฉันเพิ่งพบวิธีแก้ปัญหานี้ แต่ในกรณีของฉันมันใช้ไม่ได้:

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

orphanRemoval = trueไม่มีผล


1
ฉันต้องทำความสะอาดและสร้างก่อนที่การเปลี่ยนแปลงจะมีผล
maralbjo

ว้าวฉันมองหามาเป็นชั่วโมงแล้วว่าทำไมการเพิ่ม CascadeType ทั้งหมดใน ManyToOne ของฉันไม่ใช่การลบแบบเรียงซ้อน ทำความสะอาดและสร้างและใช้งานได้ ขอบคุณ @maralbjo
Andrew Mairose


2

ฉันมีปัญหาเดียวกันและฉันสงสัยว่าทำไมเงื่อนไขด้านล่างนี้ไม่ได้ลบเด็กกำพร้า รายการอาหารไม่ได้ถูกลบใน Hibernate (5.0.3.Final) เมื่อฉันเรียกใช้แบบสอบถามลบชื่อ:

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

จากนั้นฉันก็จำได้ว่าฉันต้องไม่ใช้คิวรีลบชื่อแต่เป็น EntityManager ในขณะที่ฉันใช้EntityManager.find(...)วิธีดึงข้อมูลเอนทิตีแล้วEntityManager.remove(...)ลบมันอาหารก็ถูกลบเช่นกัน


2

เพียง@OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true).

ลบtargetEntity = MyClass.classมันใช้งานได้ดี



0

ฉันใช้การแมปแบบหนึ่งต่อหนึ่ง แต่เด็กไม่ได้รับการลบ JPA กำลังละเมิดคีย์ต่างประเทศ

หลังจากใช้ orphanRemoval = true ปัญหาได้รับการแก้ไขแล้ว


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") private Child child;
วีพินเชาฮาน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.