2009-02-23 15 views
47

का उपयोग कर मैं एक ग्राहक जो आलसी आरंभीकरण उपयोग करना चाहता है के लिए एक परियोजना पर काम कर रहा हूँ LazyInitializationException हल करने के लिए कैसे। डिफ़ॉल्ट आलसी लोडिंग मोड के साथ कक्षाओं को मैप करते समय उन्हें हमेशा "आलसी प्रारंभिक अपवाद" मिलता है।जब JPA और हाइबरनेट

@JoinTable(name = "join_profilo_funzionalita", joinColumns = {@JoinColumn(name = "profilo_id", referencedColumnName = "profilo_id")}, inverseJoinColumns = {@JoinColumn(name = "funzionalita_id", referencedColumnName = "funzionalita_id")}) 
//@ManyToMany(fetch=FetchType.EAGER) - no exceptions if uncommented 
@ManyToMany 
private Collection<Funzionalita> funzionalitaIdCollection; 

क्या इस त्रुटि से बचने के लिए जेपीए कक्षाओं का उपयोग कर एक मानक पैटर्न है?

स्निपेट का स्वागत है, आपके समय के लिए बहुत बहुत धन्यवाद।

उत्तर

5

OpenSessionInView इस समस्या से निपटने के लिए एक पैटर्न है। यहाँ कुछ जानकारी:

http://www.hibernate.org/43.html

आप जब इस पद्धति को लागू करने में सावधान रहना और निहितार्थ को समझना चाहेंगे। प्रत्येक बार जब आप दृश्य में आलसी सहयोग को नेविगेट करते हैं तो यह डेटा लोड करने के लिए एक और SQL क्वेरी को बंद कर देगा। यदि आपके उपयोग के मामले ऐसे हैं कि इन एसक्यूएल प्रश्नों की संख्या और आकार छोटा है तो इससे कोई फर्क नहीं पड़ता। सुनिश्चित करें कि कम से कम आप अपनी लॉगिंग सेटिंग्स को एडजस्ट करते हैं ताकि आप देख सकें कि डेटा लोड करने के लिए पृष्ठभूमि में हाइबरनेट पृष्ठभूमि में "जादुई रूप से" निष्पादित है।

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

+0

यदि आप अपने सर्वर पर लोड की उम्मीद करते हैं तो ओपन सत्र का उपयोग न करें। यह उत्तर उस दिशा में एक चेतावनी का उपयोग कर सकता है। – iwein

+1

मैंने सोचा कि लिंक पैटर्न के प्रभावों को समझाने के लिए पर्याप्त होगा लेकिन मैंने मामले में कुछ चेतावनियां जोड़ दी हैं। :) –

7

LazyInitializationException मतलब है कि आप संग्रह बुला रहे हैं के बाद हाइबरनेट सत्र बंद कर दिया गया है, या वस्तु के बाद सत्र से अलग कर दिया गया है।

आप की जरूरत है या तो फिर से संलग्न वस्तु सत्र हाइबरनेट करने के लिए, जगह है जहाँ आप संग्रह बुला रहे हैं बदलने के लिए, या जहां सत्र एक उच्च स्तर के लिए बंद हो जाता है की सीमा पर ले जाएँ।

+12

अच्छा है लेकिन कैसे? –

+2

बिल्कुल, हमें WHAT हिस्सा मिला; सवाल कैसे है! – Nikhil

16

वहाँ पहले से लाने के लिए गुण कई तरीके हैं, इसलिए वे देखते हैं के बाद सत्र बंद कर दिया है:

  1. कॉल उचित गेटर। क्षेत्र के बाद बीन में लाया जाता है, सत्र बंद होने के बाद वहां होता है।
  2. आप EJBQL क्वेरी में फ़ील्ड प्रारंभ कर सकते हैं, JOIN FETCH कीवर्ड देखें।
  3. यदि आप एक हाइबरनेट संस्करण पर हैं जो इसे समर्थन देता है तो उपलब्ध सेटिंग्स .ENABLE_LAZY_LOAD_NO_TRANS सक्षम करें।

कई समस्याओं हो सकता है जब आप इन समाधानों को आज़माएं:

  1. ही टिककर खेल 'मंगलाचरण JIT कम्पाइलर द्वारा दूर अनुकूलित किया जा सकता है (कभी कभी यह कुछ समय लगता है)।
  2. संस्थाओं आप JOIN FETCH की कोशिश कर रहे कई 'कई' सूची के शामिल संबंधों के माध्यम से जोड़ा जा सकता है। इस मामले में परिणामस्वरूप क्वेरी संदिग्ध परिणाम देता है और हाइबरनेट आपके डेटा को एक ही क्वेरी में लाने से इंकार कर देगा।
  3. पहले से ही एक interesting bug related to AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS है। और वहां और अधिक होगा क्योंकि हाइबरनेट लोग कहते हैं: नोट: यह लेनदेन के बाहर हो सकता है और सुरक्षित नहीं है। सावधानी से प्रयोग करें। आप अपने ज्यादातर पर हैं।

सबसे अच्छा तरीका JOIN FETCH पहले कोशिश करना है। यदि यह काम नहीं करता है तो गेटर दृष्टिकोण का प्रयास करें। यदि वह जेआईटी कंपाइलर द्वारा रनटाइम पर गड़बड़ हो जाता है, तो परिणाम को public static volatile Object पर असाइन करें।

या हाइबरनेट का उपयोग बंद ...

+0

बिंदु (3) मुद्दे को नोट करने के लायक है बग को संस्करण 4.1.7 के रूप में बंद कर दिया गया है। लिखने के समय यहां एक संबंधित खुली समस्या है: https: //hibernate.atlassian.net/browse/HHH-8782। –

+2

"या हाइबरनेट का उपयोग करना बंद करें ..." ... आमीन। –

4

आप संग्रह का उपयोग कर रहे हैं और आप आलसी लोड हो रहा है के साथ यह तो प्रारंभ सत्र बंद होने से पहले उस संग्रह का उपयोग करना चाहते हैं। यदि सत्र उसके बाद बंद है यदि आप उपयोग करना चाहते हैं तो आपको lazyinitializeException मिल जाएगा क्योंकि आलसी डिफ़ॉल्ट रूप से आज़माएं।

60

हाइबरनेट 4.1.6 अंत में इस समस्या को हल करती है: https://hibernate.atlassian.net/browse/HHH-7457

आप हाइबरनेट-संपत्ति hibernate.enable_lazy_load_no_trans निर्धारित करने की आवश्यकता = सच

यहाँ

कैसे स्प्रिंग में यह करना है:

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="myDataSource"/> 
    <property name="packagesToScan" value="com.mycompany.somepackage"/> 
    <property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/> 
    <property name="jpaDialect" ref="jpaDialect"/> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.enable_lazy_load_no_trans">true</prop> 
     </props> 
    </property> 
</bean> 

देखा; अब आपको हाइबरनेट-सत्र ("जेपीए-स्पीच" में दृढ़ता-संदर्भ) के बाहर अपने डोमेन-मॉडल को नेविगेट करते समय LazyInitializationException की चिंता करने की आवश्यकता नहीं है)

+3

क्या मुझे यह देखकर खुशी हुई! बहुत बहुत धन्यवाद। – Oversteer

+1

क्या आप अपने उत्तर में जोड़ सकते हैं कि यह संपत्ति वास्तव में क्या करती है? कार्यान्वयन डेटा स्थिरता या प्रदर्शन के लिए गंभीर प्रभाव डाल सकता है। शायद दोनों। – iwein

+1

यह विकल्प लेनदेन के बाहर आलसी-एसोसिएशन लोड करता है, जिसका अर्थ यह है कि डेटा माता-पिता की इकाई के अनुरूप नहीं हो सकता है। लेकिन यह वसंत के OpenEntityManagerInViewFilter का उपयोग करने से भी बदतर नहीं है, जो लेनदेन के बाहर सामान भी लोड करता है। मैं फील्ड-आधारित मैपिंग का उपयोग कर रहा हूं और जेआईटी जेनरेट प्रॉक्सी को गड़बड़ नहीं कर रहा हूं। – andreak

14

ध्यान दें कि आपको hibernate.enable_lazy_load_no_trans प्री हाइबरनेट 4.1.7 का उपयोग नहीं करना चाहिए , क्योंकि यह कनेक्शन रिसाव करता है। देखें https://hibernate.onjira.com/browse/HHH-7524

+1

यह काम करता है, लेकिन अब मेरे पास हाइबरनेट मैपिंग के साथ रिकर्सिव साइक्लिंग समस्या है –

1

ओरेकल जावा ट्यूटोरियल बताते हैं कि "एंटरप्राइज़ बीन्स लेनदेन का समर्थन करते हैं, जो तंत्र साझा वस्तुओं की समवर्ती पहुंच का प्रबंधन करते हैं।" इसलिए, आलसी Fetch मुद्दों को संभालने के लिए मैं एक स्टेटलेस जावा सत्र बीन बनाते हैं और फिर विधि से लौटने से पहले मुझे आवश्यक सभी उप वर्ग प्राप्त करते हैं। यह आलसी fetch अपवाद से बचाता है। ओरेकल ने इसे "सत्र फैकेड" कोर जे 2 ईई पैटर्न के रूप में भी संदर्भित किया है। यह पैटर्न उल्लिखित कुछ अन्य अभ्यासों से बेहतर लगता है।

2

The best way to solve the LazyInitializationException आपकी इकाई क्वेरी में जॉइन फ़ेच निर्देश का उपयोग करना है।

EAGER loading प्रदर्शन के लिए खराब है।

जो तुम यूआई प्रतिपादन के लिए खुला होना करने के लिए, क्योंकि वे या तो डेटाबेस कनेक्शन की आवश्यकता का उपयोग कभी नहीं करना चाहिए (में खोलें सत्र: इसके अलावा, वहाँ विरोधी पैटर्न जैसे हैं देखें), या शुरुआती पर्सिस्टेंस संदर्भ (hibernate.enable_lazy_load_no_trans) के बाहर लाए गए प्रत्येक आलसी संगठन के लिए डेटाबेस कनेक्शन की आवश्यकता है।

कभी-कभी, आपको संस्थाओं की भी आवश्यकता नहीं होती है, और एक डीटीओ प्रक्षेपण भी बेहतर होता है। आपको केवल उन्हीं संस्थाएं प्राप्त करनी चाहिए जब आपको उन्हें संशोधित करने की आवश्यकता हो। केवल पढ़ने के लिए लेनदेन के लिए, DTO projections are better

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