2013-07-13 11 views
7

HiAll को सौंपा गया थाहाइबरनेट: एक इकाई प्रति पहले से ही, एक अलग इकाई

मैं समझने के लिए वर्तमान में प्रयास करते हैं, क्या मेरी कोडिंग और इकाई मॉडल में गलत है मैं हाइबरनेट 4.2 CRUD आपरेशन के लिए उपयोग सिर्फ जेनेरिक डीएओ के साथ सभी और orphanRemoval = सच कैस्केडिंग के साथ पैटर्न और एनोटेटेड इकाइयां। मेरे पास डेप्लान इकाई डेप्लान एलिमेंट कमजोर इकाई के साथ OneToMany संबंध के साथ है। DayPlanElement java.util.Set में सहेजे गए हैं। प्रत्येक DayPlanElement में एक संपत्ति "ऑर्डर" है।

DayPlan भी एक इकाई व्यक्ति को OneToMany संबंध नहीं है। इकाई व्यक्ति java.util में सहेजा गया। सूची

DayPlanElementDayPlanElementEntry कमजोर संस्था के लिए OneToMany संबंध नहीं है। java.util.Set बचाने के लिए इस्तेमाल किया। व्यक्ति इकाई भी डेप्लानएलेमेंटएन्ट्री कमजोर इकाई के साथ OneToMany संबंध। java.util.Set सहेजने के लिए उपयोग किया जाता है। डेप्लान, डेप्लान एलिमेंट और व्यक्ति इकाइयों में आईडी के रूप में, मेरे आवेदन द्वारा प्रबंधित स्ट्रिंग के रूप में आईडी है। DayPlanElementEntry कमजोर इकाई में एक समग्र आईडी है: एंबेडेड आईडी के साथ एनप्लेटेड डेप्लानएलेमेंटएन्ट्रीआईडी, जिसमें parentPersonId और dayPlanElementId शामिल है। यह

दूसरे शब्दों में कल्पना करें, यह एक तालिका मौजूद है, दिन योजना का प्रतिनिधित्व करता है। कॉलम 0 से 24 तक के घंटे हैं। पंक्तियां व्यक्ति हैं, जिन्हें दिन की योजना से परिचालन जारी रखना होगा। प्रत्येक कॉलम DayPlanElement इकाई होगी। प्रत्येक पंक्ति व्यक्ति इकाई होगी। और प्रत्येक सेल DayPlanElementEntry इकाई होगी।

यदि मैं सिर्फ तालिका में नए तत्वों (व्यक्तियों को भी) जोड़ता हूं और इसे हटा देता हूं (इसे सूची से भी हटा देता हूं और फिर DayPlanDAO.merge (dayPlan) को कॉल करता हूं - मुझे कैस्केडिंग और अनाथ रिमूवल पर आशा है) - मुझे कोई समस्या नहीं है।

सिर्फ अगर मैं दिया व्यक्तियों (सिर्फ java.util.List भीतर संचालन को हटाने) और कॉल DayPlanDAO.merge (dayPlan) को पुन: व्यवस्थित करने की कोशिश - निम्नलिखित excepion फेंक दिया जाएगा:

Caused by: java.lang.IllegalStateException: 
Error occurred while storing entity 
[DayPlanElementEntry [getDayPlanMode()=NONE, getCompositeId()=DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6], hashCode=-2039940039]]. 

An entity copy 
[org.hw.domain.DayPlanElementEntry#DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6]] 

was already assigned to a different entity 

[org.hw.domain.DayPlanElementEntry#DayPlanElementEntryId [parentPersonId=874c8eac-8796-478d-a4d5-dd011f7d6a4b, dayPlanElementId=ab683a25-633e-419e-89b6-4aef7829d4f6]]. 

     at org.hibernate.event.internal.EventCache.put(EventCache.java:192) 

     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:285) 

     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) 

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

मैं घटना कैश के लिए test class पाया है, लेकिन अब मैं निम्नलिखित उपयोग के मामले परीक्षण समझ में नहीं आता:

@Test 
public void testCopyAssociatedWith2ExistingEntities() { 
session.getTransaction().begin(); 
Simple entity1 = new Simple(1); 
session.persist(entity1); 
Simple copy1 = new Simple(1); 
cache.put(entity1, copy1); 
Simple entity2 = new Simple(2); 
session.persist(entity2); 
Simple copy2 = new Simple(2); 
cache.put(entity2, copy2); 
session.flush(); 

try { 
cache.put(entity1, copy2); 
fail("should have thrown IllegalStateException"); 
} 
catch(IllegalStateException ex) { 
// expected 
assertTrue(ex.getMessage().startsWith("Error occurred while storing entity [org.hibernate.event.internal.EventCacheTest$Simple#1].")); 
} 
session.getTransaction().rollback(); 
} 

....

@Entity 
private static class Simple { 
@Id 
private int value; 

public Simple(int value) { 
this.value = value; 
} 

public int getValue() { 
return value; 
} 

public void setValue(int value) { 
this.value = value; 
} 
} 

हम तो हम यह जारी रहती है आईडी = 1 के साथ सरल इकाई ENTITY1 है,। फिर हम सरल इकाई कॉपी 1 बनाते हैं और ईवेंट कैश में इसे मूल्य के रूप में डालते हैं। कुंजी के रूप में जारी इकाई * * प्रयुक्त। फिर हम क्रमांक 2 = के साथ एक सरल इकाई * * बनाते हैं, तो यह जारी रहती है, और उसके बाद प्रतिलिपि बनाने * * आईडी 2 के साथ इकाई और घटना कैश में मूल्य के रूप में डाल दिया। कुंजी के रूप में इकाई 2 उपयोग किया जाता है। ऐसी स्थिति गलत क्यों है और क्यों उम्मीद की जाती है, कि अवैध स्तर अपवाद को फेंक दिया जाना चाहिए ??

आपकी मदद के लिए धन्यवाद!

+1

वही समस्या! कृपया, अगर आपको कोई समाधान मिल गया है - इसे –

उत्तर

1

यदि यह किसी परीक्षण के संदर्भ में है, तो मेरा सुझाव है कि आप अपने session.flush() को session.clear() के साथ फ़ॉलो करें। यह आपके सत्र कैश को प्रभावी ढंग से साफ़ करेगा जो इस मुद्दे के मूल में प्रतीत होता है। (मैं के बारे में सोच सकते हैं) इस समस्या के लिए

संभावित कारण हैं:

  • एक ही इकाई प्रति अलग इकाई कुंजी के तहत कैश करने के लिए जोड़ा जा रहा है। अधिक जानकारी प्राप्त करने के लिए EventCache.java में पाए गए पुट विधि के तहत ब्रेकपॉइंट सेट करें।
  • हाइबरनेट के संस्करण में एक नवप्रारंभित बग जिसका आप उपयोग कर रहे हैं।
10

हाइबरनेट संस्करण 4.3.4 और आसपास के लिए, एक फिक्स आउट है।

<dependency> 
    <groupId>com.intersult</groupId> 
    <artifactId>jpa-fix</artifactId> 
    <version>1.1</version> 
</dependency> 

इस सुधार में इस तरह के एक के साथ MergeEventListener बदल देता है, कि मर्ज इस तरह संभालती है: बस इस विरूपण साक्ष्य जोड़ें।

+0

पोस्ट करें, क्या? इसने मेरे हाइबरनेट विलय मुद्दों को ठीक किया! यह कैसे काम करता है? क्या आपके पास इस फिक्स के लिए कोई आधिकारिक दस्तावेज है? – kazmer

+0

https://www.intersult.com/wiki/page/JPA%20Fix – Tires

+0

हम्म पर कहने के लिए बहुत कुछ नहीं है, जो काम करता है ... – invis

5

मुझे अपने कोड के साथ एक ही समस्या है। इस समाधान का प्रयास करें:

शायद यह दो "cascade.all" के कारण होता है। डेप्लान इकाई के साथ काम करते समय, इसमें दोनों सूची और सूची होगी और दोनों में 1: एम से DayPlanElementEntry होगा।

तो दो "cascade.all" को लगता है कि DayPlanElementEntry को व्यक्ति को सौंपा गया है जब DayPlanElement इसे एक्सेस करने का प्रयास करता है, यहां तक ​​कि यह वही DayPlanElementEntry है।

मुझे उम्मीद है कि यह मदद करता है।

बेस्ट, चोंग

+0

समाधान की तलाश में दो घंटे, और यह बहुत आसान था, और एक ही समय में बेवकूफ .... धन्यवाद –

+0

तब समाधान क्या है? मुझे एक ही समस्या है डी: –

3

यह 4.2.15/4.3.6 या इसके बाद के हाइबरनेट और अपने persistence.xml निम्न पंक्तियां जोड़ें पर अपग्रेड करके resoloved जा सकता है:

<property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

देखें अधिक जानकारी के लिए https://hibernate.atlassian.net/browse/HHH-9106

0

क्या आइटम और घटक के बीच आपका संबंध यूनिडायरेक्शनल या बिडरेक्शनल है? यदि यह द्विपक्षीय है तो सुनिश्चित करें कि आपके पास कैस्केड नहीं है। MERGE कॉल आइटम पर वापस जा रहे हैं।

कैस्केड टाइप को हटाएं।अपने रिश्ते से विलय करें

0

जेपीए कॉन्फ़िगरेशन फ़ाइल में नीचे जोड़ें यह समस्या हल करेगा।

कई रिश्तों में यदि कई इकाइयां पहले से मौजूद इकाइयों के साथ विलय ऑपरेशन करते समय दोहराई जा रही हैं तो हाइबरनेट उनके बीच अंतर करने में सक्षम नहीं होगा जब तक कि हम उसे अंतर प्राप्त करने में मदद न करें।

properties.put("hibernate.event.merge.entity_copy_observer", "allow"); 
संबंधित मुद्दे