2012-10-31 47 views
14

मेरा प्रश्न यहां मेरे अन्य प्रश्न Explicit delete on JPA relationships जैसा ही है, लेकिन मैंने इसे और अधिक विस्तृत उत्तरों की गारंटी देने के लिए इसे सरल बनाने के बारे में सोचा।क्यों विलय को किसी रिश्ते में एक से अधिक पर कैस्केड नहीं किया गया है

कल्पना कीजिए कि मेरे माता-पिता और बच्चे के बीच एक बहुत ही रिश्ते है।

@Entity 
public class Parent { 
    private String name; 
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    private List<Child> children; 
} 
@Entity 
public class Child { 
    private String name; 
    @ManyToOne 
    private Parent owner; 
} 

मेरी UI में, मैं माता-पिता की एक सूची दिखा रहा हूँ। उपयोगकर्ता एक माता-पिता का चयन कर सकता है और वह अपने बच्चों की सूची संपादित कर सकता है। इसे दिखाने के लिए, मैंने वर्तमान पेरेंट संपादित का प्रतिनिधित्व करने के लिए एक वर्तमान पैरेंट चर का उपयोग किया है। उपयोगकर्ता बच्चों के नाम को जोड़ने/संपादित करने का विकल्प चुन सकता है।

बटन पर क्लिक करने पर, मैं एक ईजेबी कॉल का उपयोग करके नए बच्चों की सूची को सहेज लेगा।

@ViewScoped 
public class MyBean(){ 
    private Parent currentParent; 
    @EJB 
    private MyEJB myEJB; 

    public void saveChanges(){ 
     myEJB.save(currentParent); 
    } 
} 

मेरे EJB कॉल इस तरह दिखता है।

@Stateless 
public class MyEJB{ 
    @PersistenceContext(unitName = "MyPU") 
    private EntityManager em; 

    public void save(Parent parentNew){ 
     Parent pOld = em.find(entityClass, p.getId()); 
     if(pOld !=null){ 
      pOld.setName(parentNew.getName()); 
      pOld.setChildren(parentNew.getChildren()); 
      em.merge(pOld); 
     } 
    } 
} 

मेरे समस्या यह है कि, मैं माता-पिता का नाम, लेकिन बच्चों सूची में कोई परिवर्तन डीबी में प्रतिबिंबित नहीं होता है को बदलने में सक्षम हूँ। यह बच्चों को हटाने/अपडेट/जोड़ने के लिए किसी भी SQL को परिवर्तित या निष्पादित नहीं करता है।

कारण क्या हो सकता है?

अद्यतन

खैर कुछ परीक्षण और त्रुटि के बाद और विभिन्न लिंक के माध्यम से पढ़ने, ऐसा लगता है कि मेरे @onetomany में orphanRemoval विकल्प सेट मेरी समस्या का समाधान होगा। Eclipselink विलय के दौरान अनाथ पंक्तियों को स्वचालित रूप से हटा देता है।

तो जेपीए जटिलता के लिए बहुत ..

@Entity 
public class Parent { 
    private String name; 
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER,orphanRemoval = true) 
    private List<Child> children; 
} 
+0

शायद यह मदद करेगा: http://stackoverflow.com/questions/10656765/handling-collection-updates-with-jpa – JMelnik

+0

हाय, मुझे यकीन नहीं है कि मुझे उस लिंक का जवाब मिल गया है, तो आपका मतलब है कि मेरे पास है संग्रह के माध्यम से लूप करने और इसे एक-एक करके बचाने के लिए? मैंने वास्तव में सोचा कि eclipselink मेरे संग्रह की बचत को संभालेगा? तो उदाहरण के लिए मेरे पास एक इकाई में 5 बच्चे हैं, और फिर मैंने इसे केवल दो बच्चों के साथ संपादित किया, जब मैं विलय ऑपरेशन को कॉल करता हूं, तो यह पंक्तियों को हटाने/जोड़ने का ख्याल रखेगा। जानकारी के लिए धन्यवाद –

उत्तर

1

आपका प्रश्न What could be the cause?। कारण parentNew की मान सामग्री है। यदि parentNew निम्न कारणों में से एक है, तो यह बच्चे को प्रभावित/अपडेट नहीं करेगा।

  1. कोई संदर्भ उदाहरण माता-पिता और बाल वीजा वीजा नहीं। --->यह अपवाद फेंक देगा।
  2. Parent पैरामीटर मान Clild की शून्य या खाली सूची है ->यह आपका कारण होगा।
  3. Child यूआई से अद्यतन नाम प्राप्त नहीं है .-->यह आपका कारण होगा।

उदाहरण। मैं इसे जल्दी लिखता हूँ। यह ठीक है।

पहले से ही डीबी

Parent      Child 
================== ======================================= 
'P001', 'Parent 1' 'C002', 'Child 2', 'P001' 
        'C003', 'Child 3', 'P001' 
        'C001', 'Child 1', 'P001' 

में डेटा मौजूद Upldated के बाद:

Parent      Child 
==================   ======================================= 
'P001', 'Update Parent 1' 'C002', 'Update Child 2', 'P001' 
          'C003', 'Update Child 3', 'P001' 
          'C001', 'Update Child 1', 'P001' 

List<Child> clidList = new ArrayList<Child>(); 
Parent parent = new Parent("P001", "Update Parent 1", clidList); 
Child c1 = new Child("C001", "Update Child 1", parent); 
Child c2 = new Child("C002", "Update Child 2", parent); 
Child c3 = new Child("C003", "Update Child 3", parent); 
clidList.add(c1); 
clidList.add(c2); 
clidList.add(c3); 

Parent existingParent = em.find(Parent.class, parent.getId()); 
existingParent.setName(parent.getName()); 
existingParent.setChildren(parent.getChildren()); 
em.merge(existingParent); 
5

इस मर्ज के साथ एक मानक समस्या है। संग्रह में बाल वस्तुओं में परिवर्तन उठाए जाएंगे।

मर्ज कॉल केवल वस्तुओं है कि सूची में हैं से अधिक झरना कर सकते हैं, तो सूची में नहीं वस्तुओं में परिवर्तन खो जाते हैं। दुर्भाग्य से, oneToMany संबंध का स्वामी नहीं है: बच्चे के ManyToOne करता है। तो बच्चे संस्थाओं मर्ज करने परिवर्तन देखने की बात के लिए और डेटाबेस के लिए धक्का दिया की जरूरत है। बाल संस्थाएं स्वतंत्र वस्तुओं हैं और बदले जाने पर व्यक्तिगत रूप से विलय करने की आवश्यकता है। वह, या विलय पाने के लिए एक अलग माता पिता/पेड़ में जोड़ा गया।

+0

हाय धन्यवाद, तो क्या आप सुझाव है कि मैं क्या करते हो? –

+1

विकल्पों में से कोई भी संख्या। यदि संभव हो तो उन्हें एक अलग माता-पिता में जोड़ना होगा। या अगर वे अपने माता-पिता से स्वतंत्र नहीं हो सकता है, उन्हें अनाथ हटाने के साथ निशान तो वे जब dereferenced नष्ट हो जाती हैं। या पैरेंट को पहले ढूंढकर माता-पिता के लिए मर्ज कॉल में संग्रह में अंतर को संभालें और मर्ज करने के लिए पारित ऑब्जेक्ट से अनुपलब्ध बच्चों को ठीक करना - यह किसी ईवेंट में भी करने योग्य हो सकता है। या बस सुनिश्चित करें कि ऐप कॉल बच्चों पर विलय हो जाता है जो इसे माता-पिता से हटा देता है। – Chris