2017-03-22 7 views
12

मैं इस तरह एक हाइबरनेट इकाई एक की एक प्रतिलिपि बनाने के लिए कोशिश कर रहा हूँ के साथ हाइबरनेट संग्रह की एक प्रतिलिपि बनाने के लिए कैसे:झरना = "सभी, हटाने-अनाथ"

A a = (A) session.get(A.class, id); 
session.evict(a); 
a.setId(null); 
session.save(a); 

हालांकि यह काम नहीं करता है और मैं निम्नलिखित expetion मिलती है:

org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.test.A.B 

इसकी ग्रहण करने के लिए इस त्रुटि होता सुरक्षित वजह से मैं इकाई एक में परिभाषित बी इकाई का एक संग्रह है:

<list name="B" table="B" lazy="false" cascade="all,delete-orphan"> 
    <key column="A_ID" not-null="true"/> 
    <index column="X"/>    
    <one-to-many class="com.test.B"/> 
</list> 

एंट्री ए की प्रतिलिपि बनाना कैसे संभव है, इसके बारे में एंटील्स बी के संग्रह सहित, इसके बारे में नाखुश होने के बिना?

+0

आपका हाइबरनेट संस्करण क्या है? –

+0

हाइबरनेट संस्करण 3 है।2 – user1985273

+1

कृपया स्पष्ट करें: क्या आप प्रतिलिपि इकाई में संग्रह में * समान * तत्व रखना चाहते हैं या आप संग्रह में तत्वों को प्रतिलिपि बनाना चाहते हैं? – Andremoniy

उत्तर

1

ऐसी वस्तुओं की प्रतिलिपि बनाने का कोई स्वचालित तरीका नहीं है। आम तौर पर, कॉपी ऑब्जेक्ट को अन्य ऑब्जेक्ट्स से जोड़ा जा सकता है जो अन्य ऑब्जेक्ट्स आदि से जुड़े होते हैं, ताकि आप डेटाबेस के एक बड़े हिस्से की प्रतिलिपि बना सकें। प्रतिलिपि बनाने के लिए आपके द्वारा उपयोग किए जाने वाले किसी भी उपकरण को पता होना चाहिए कि ऑब्जेक्ट ग्राफ़ में प्रतिलिपि रोकने के लिए, कॉपी करने के लिए क्या नहीं है (हाइबरनेट इकाइयों के संदर्भ में वे आईडी, संस्करण कॉलम और इसी तरह के हैं), और इसी तरह।

हालांकि आप मैन्युअल रूप से लिखने के लिए आवश्यक बॉयलरप्लेट कोड से बचने के लिए Dozer जैसे ढांचे का उपयोग कर सकते हैं।

संग्रह रीअसाइनमेंट मुद्दे के बारे में, आप, B उदाहरणों में से एक ही संग्रह दो अलग A रों करने के लिए आवंटित किया जा रहा नहीं हो सकता है के रूप में यह तार्किक तो एक many-to-many संघ होगा। यह कुछ भी है जो आपको मैन्युअल रूप से देखभाल करने की आवश्यकता होगी, क्योंकि यह आपके व्यावसायिक उपयोग के मामले के लिए विशिष्ट है।

इसके अलावा, सुनिश्चित करें कि आप एक ही संग्रह प्रॉक्सी को दूसरों में एक इकाई उदाहरण से पुन: उपयोग नहीं करते हैं, क्योंकि हाइबरनेट उन्हें अपने मूल माता-पिता से आंतरिक रूप से जोड़ता है - हमेशा नए उदाहरणों में एक नया संग्रह बनाएं (जिसमें हो सकता है या नहीं हो सकता है एक ही तत्व)।

1

यदि आप किसी मौजूदा इकाई की प्रतिलिपि बनाना चाहते हैं - इसे संशोधित करें - और इसे नई इकाई के रूप में सहेजें, तो आपको उस ऑब्जेक्ट को गहरी प्रतिलिपि बनाने की आवश्यकता है। आप Serializing द्वारा ऑब्जेक्ट की गहरी प्रतिलिपि कर सकते हैं और फिर उस ऑब्जेक्ट को डी-सीरियलाइज कर सकते हैं।

public Object deepCopy(Object input) { 

    Object output = null; 
    try { 
     // Writes the object 
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
     ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 
     objectOutputStream.writeObject(input); 

     // Reads the object 
     ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); 
     ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); 
     output = objectInputStream.readObject(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return output; 
} 
3

मुझे पहले मेरी परियोजना में एक ही समस्या थी।

मेरे लिए यह सूची-प्रविष्टियों की आईडी को शून्य पर सेट करने के लिए काम करता है।

// make copy a of aOriginal by using serialisation clone 
a.setId(null); 
for (B b : a.getBs()) { 
    b.setId(null); 
} 
session.save(a); 

क्लोन खुद के लिए मैं Apache SerializationUtils clone इस्तेमाल किया।

कारण यह है कि हाइबरनेट "प्रतिलिपि" इकाई के लिए पहले से ही सूचीबद्ध सूची-प्रविष्टियों को "पुन: उपयोग" करने का प्रयास करता है। लेकिन यह पहले से ही जारी है सूची-प्रविष्टियां मूल इकाई से जुड़ी हैं। इसलिए यह इकाई में सूची को "बदल" करने का प्रयास करता है, क्योंकि इकाई बदल गई है। लेकिन अगर आप "डिलीट-अनाथ" के साथ एनोटेटेड हैं तो आप सूची को नहीं बदल सकते हैं (आप केवल सूची की प्रविष्टियों को संशोधित कर सकते हैं, लेकिन सूची स्वयं ही नहीं)। तो अपवाद फेंक दिया जाता है।

यदि मैं सूची-प्रविष्टि-आईडी को शून्य पर सेट करता हूं, तो उन्हें न्यूले भी डाला जाएगा। और ऑब्जेक्ट पदानुक्रम (केवल मुख्य इकाई के बजाय) डुप्लिकेट किया गया है। तो exeption अब फेंक दिया नहीं है।

संबंधित मुद्दे