JPA OneToMany बच्चे को नहीं हटा रहा है


158

मुझे @OneToManyमाता-पिता और बच्चे की संस्था के बीच एक सरल मानचित्रण में समस्या है । सभी अच्छी तरह से काम करते हैं, केवल जब मैं उन्हें संग्रह से हटाता हूं तो बच्चे के रिकॉर्ड हटाए नहीं जाते हैं।

माता पिता:

@Entity
public class Parent {
    @Id
    @Column(name = "ID")
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
    private Set<Child> childs = new HashSet<Child>();

 ...
}

बच्चा:

@Entity
public class Child {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="PARENTID", nullable = false)
    private Parent parent;

  ...
}

अगर मैं अब चिल्ड सेट से बच्चे को हटाता हूं, तो यह डेटाबेस से डिलीट नहीं होता है। मैंने child.parentसंदर्भ को स्पष्ट करने की कोशिश की , लेकिन यह भी काम नहीं किया।

संस्थाओं को एक वेब अनुप्रयोग में उपयोग किया जाता है, डिलीट एक अजाक्स अनुरोध के हिस्से के रूप में होता है। मेरे पास हटाए गए चिल्ड की सूची नहीं है जब सेव बटन दबाया जाता है, तो मैं उन्हें अंतर्निहित रूप से हटा नहीं सकता।

जवाबों:


253

JPA का व्यवहार सही है ( विनिर्देश के अनुसार अर्थ ): ऑब्जेक्ट केवल इसलिए नहीं हटाए गए क्योंकि आपने उन्हें OneToMany संग्रह से निकाल दिया है। ऐसे विक्रेता-विशिष्ट एक्सटेंशन हैं जो ऐसा करते हैं, लेकिन मूल JPA इसके लिए पूरा नहीं करता है।

आंशिक रूप से यह इसलिए है क्योंकि जेपीए वास्तव में नहीं जानता है कि क्या उसे संग्रह से हटाए गए कुछ को हटाना चाहिए। वस्तु मॉडलिंग के संदर्भ में, यह संरचना और "एकत्रीकरण * के बीच का अंतर है ।

में रचना , बच्चे इकाई माता-पिता के बिना कोई अस्तित्व नहीं है। एक क्लासिक उदाहरण हाउस और रूम के बीच है। घर और कमरों को भी हटा दें।

एकत्रीकरण एक ढीला प्रकार का संघ है और पाठ्यक्रम और छात्र द्वारा टाइप किया जाता है। पाठ्यक्रम और छात्र अभी भी मौजूद हैं (शायद अन्य पाठ्यक्रमों में)।

इसलिए आपको इस व्यवहार को (यदि उपलब्ध हो) बलपूर्वक या स्पष्ट रूप से बच्चे को हटाने और माता-पिता के संग्रह से निकालने के लिए विक्रेता-विशिष्ट एक्सटेंशन का उपयोग करने की आवश्यकता है।

मैं इससे अवगत हूँ:


अच्छी व्याख्या के लिए धन्यवाद। इसलिए यह वैसा ही है जैसा मुझे डर था। (मैंने पूछने से पहले कुछ खोज / पठन किया, बस सहेजने की इच्छा थी)। किसी तरह मैं सीधे जेपीए एपीआई और नाइट हाइबरनेट का उपयोग करने के निर्णय पर पछतावा करना शुरू कर देता हूं .. मैं चंद्रा पाटनी सूचक की कोशिश करूंगा और हाइबरनेट डिलीट_ बोरहान कैस्केड प्रकार का उपयोग करूंगा।
बर्ट

इस बारे में मेरा एक तरह का सवाल है। कृपया इस पोस्ट पर एक नज़र डालेंगे यहाँ, कृपया? stackoverflow.com/questions/4569857/…
थांग फाम

77
JPA 2.0 के साथ, आप अब orphanRemoval विकल्प का उपयोग कर सकते हैं = true
itsadok

2
महान प्रारंभिक स्पष्टीकरण और अनाथ रमोवल पर अच्छी सलाह। पता नहीं जेपीए इस प्रकार के निष्कासन के लिए जिम्मेदार नहीं था। हाइबरनेट के बारे में मुझे जो पता है, उसके बीच की बारीकियां और जेपीए वास्तव में क्या करता है, वह मद्देनजर है।
sma

रचना और पीड़ा के बीच के अंतर को उजागर करके अच्छी तरह से समझाया गया!
फेलिप लेओ

73

क्लेटस के उत्तर के अलावा, JPA 2.0 , अंतिम 2010 के बाद से, एनोटेशन orphanRemovalपर एक विशेषता का परिचय देता है @OneToMany। अधिक जानकारी के लिए यह ब्लॉग प्रविष्टि देखें ।

ध्यान दें कि चूंकि कल्पना अपेक्षाकृत नई है, इसलिए सभी JPA 1 प्रदाता के पास अंतिम JPA 2 कार्यान्वयन नहीं है। उदाहरण के लिए, हाइबरनेट 3.5.0-बीटा -2 रिलीज़ अभी तक इस विशेषता का समर्थन नहीं करता है।


ब्लॉग प्रविष्टि - लिंक टूट गया है।
स्टेफी


43

आप यह कोशिश कर सकते हैं:

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true)


2
धन्यवाद। लेकिन सवाल 1 बार जेपीए से वापस आ गया है। और यह विकल्प वापस उपलब्ध नहीं था।
बर्ट

9
फिर भी, हममें से उन लोगों के लिए यह जानना अच्छा है, जो JPA2 समय में इसके लिए एक समाधान खोजते हैं :)
एलेक्सा 4040

20

जैसा कि समझाया गया है, यह संभव नहीं है कि मैं जेपीए के साथ क्या करना चाहता हूं, इसलिए मैंने हाइबरनेट.कैशडे एनोटेशन को नियोजित किया, इसके साथ, अभिभावक वर्ग में संबंधित कोड अब इस तरह दिखता है:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.PERSIST,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();

मैं 'ALL ’का सरल उपयोग नहीं कर सकता था क्योंकि इससे माता-पिता भी नष्ट हो जाते।


4

यहां कैस्केड, हटाने के संदर्भ में, इसका मतलब है कि यदि आप माता-पिता को हटाते हैं तो बच्चे हटा दिए जाते हैं। संघ का नहीं। यदि आप हाइबरनेट को अपने जेपीए प्रदाता के रूप में उपयोग कर रहे हैं, तो आप हाइबरनेट विशिष्ट कैस्केड का उपयोग करके कर सकते हैं ।



हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.