2008-12-06 17 views
67

प्रारंभ नहीं कर सका, जिसने मुझे परेशान किया है। मैं एक बुनियादी हाइबरनेट डीएओ संरचना को लागू करने की कोशिश कर रहा हूं, लेकिन मुझे कोई समस्या है।हाइबरनेट: LazyInitializationException: प्रॉक्सी

int startingCount = sfdao.count(); 
sfdao.create(sf); 
SecurityFiling sf2 = sfdao.read(sf.getId()); 
sfdao.delete(sf); 
int endingCount = sfdao.count(); 

assertTrue(startingCount == endingCount); 
assertTrue(sf.getId().longValue() == sf2.getId().longValue()); 
assertTrue(sf.getSfSubmissionType().equals(sf2.getSfSubmissionType())); 
assertTrue(sf.getSfTransactionNumber().equals(sf2.getSfTransactionNumber())); 

यह तीसरी assertTrue जहां यह SF2 में संबंधित मान को sf में एक मूल्य की तुलना करने के कोशिश कर रहा है पर विफल रहता है:

यहाँ आवश्यक कोड है। यहां अपवाद है:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86) 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140) 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190) 
    at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java) 
    at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40) 

उत्तर

15

इसका आम तौर पर मतलब है कि स्वामित्व वाले हाइबरनेट सत्र पहले ही बंद हो चुका है। आप इसे ठीक करने के लिए निम्न में से एक कर सकते हैं:

  1. जो भी वस्तु इस समस्या को बनाने, HibernateTemplate.initialize(object name)
  2. उपयोग lazy=false अपने HBM फ़ाइलों में उपयोग करें। यहाँ
+0

को एक ही समस्या और आलसी = false यह तय था । धन्यवाद – autonomatt

+1

अब मेरे मामले में सभी दाओ स्तर के लिए 'आलसी = झूठी' का उपयोग कर रहा है, लेकिन यह पता चला है कि इसके कारण एप्लिकेशन का प्रदर्शन धीमा है, 'आलसी = सत्य' सेट करने का प्रयास किया गया है, लेकिन अब आलसी अपवाद फेंक दिया गया है, कोई सुझाव यह कैसे हो सकता है तय की। – Rachel

+0

पाकोर, क्या आप बता सकते हैं कि समाधान क्यों नहीं है और इसे कैसे समझें? – Victor

2

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

जीवन सुडौल है ... :)

+0

मुझे यकीन नहीं है कि मैं पूरी तरह से समझता हूं, क्योंकि मुझे अन्य परियोजनाओं में इसे देखने को याद नहीं है। लेकिन आप सही हैं: सेवा परत में विधियों के लिए '@ org.springframework.transaction.annotation.Transactional (readOnly = true) 'जोड़ना समस्या को हल करता है। (उस परत में हम एक इकाई ला रहे हैं और इसे डीएओ को एक और कॉल में भेज रहे हैं।) – Arjan

1

मुझे लगता है कि Piko उसकी प्रतिक्रिया है कि वहाँ HBM फ़ाइल में मतलब है। मेरे पास कर.जावा नामक एक फाइल है। मैपिंग जानकारी एचबीएम (= हाइबरनेट मैपिंग) फ़ाइल में सहेजी जाती है। कक्षा टैग में आलसी नामक एक संपत्ति है। उस संपत्ति को सही पर सेट करें। निम्नलिखित एचबीएम उदाहरण आलसी संपत्ति को झूठी पर सेट करने का एक तरीका दिखाता है।

` आईडी ... '

आप एनोटेशन का उपयोग कर रहे हैं, तो बजाय हाइबरनेट documenation में लग रहे हो। http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/

मुझे आशा है कि इससे मदद मिलेगी।

4

अगर आप Lazy अपने विधि लोड हो रहा है राज्यविहीन सत्र EJB

3

के लिए

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) साथ एनोटेट किया जाना चाहिए हम इस त्रुटि के साथ-साथ सामना करना पड़ा उपयोग कर रहे हैं। हमने इस मुद्दे को हल करने के लिए क्या किया है, हमने हाइबरनेट मैपिंग फ़ाइल में आलसी = झूठी जोड़ा है।

ऐसा प्रतीत होता है कि हमारे पास एक कक्षा ए थी जो एक सत्र के अंदर है जो एक और कक्षा बी लोड करता है। हम कक्षा बी पर डेटा तक पहुंचने की कोशिश कर रहे हैं लेकिन इस कक्षा बी को सत्र से अलग किया गया है।

हमें इस कक्षा बी का उपयोग करने के लिए आदेश में, हम कक्षा में एक के हाइबरनेट मैपिंग फ़ाइल आलसी = false विशेषता निर्दिष्ट किया था। उदाहरण के लिए,

 <many-to-one name="classA" 
       class="classB" 
       lazy="false"> 
     <column name="classb_id" 
       sql-type="bigint(10)" 
       not-null="true"/> 
    </many-to-one> 
68

समस्या यह है कि आप एक वस्तु है कि है detached में एक संग्रह का उपयोग करने की कोशिश कर रहे हैं। वर्तमान सत्र में संग्रह तक पहुंचने से पहले आपको ऑब्जेक्ट को फिर से संलग्न करने की आवश्यकता है। आपको लगता है कि के माध्यम से

session.update(object); 

lazy=false का उपयोग करते हुए एक अच्छा समाधान नहीं है, क्योंकि आप दूर हाइबरनेट की लेज़ी प्रारंभ सुविधा फेंक रहे हैं कर सकते हैं। जब lazy=false, संग्रह एक ही समय है कि वस्तु अनुरोध किया जाता है पर स्मृति में भरी हुई है। इसका मतलब यह है कि अगर हम 1000 मदों के साथ एक संग्रह है, वे सब, स्मृति में लोड किया जाएगा के बावजूद हम उन्हें नहीं पहुंच सकता है या करने के लिए जा रहे हैं। और यह अच्छा नहीं है।

कृपया इस article जहां यह समस्या बताते हैं, संभव समाधान पढ़ सकते हैं और यही कारण है कि इस तरह से कार्यान्वित किया जाता है। साथ ही, सत्र और लेनदेन को समझने के लिए आपको this other article पढ़ना होगा।

7

आप जेपीए एनोटेशन के साथ हाइबरनेट का उपयोग कर रहे हैं तो यह उपयोगी होगा। आपकी सेवा कक्षा में @PersistenceContext के साथ इकाई प्रबंधक के लिए एक सेटटर होना चाहिए। @PersistenceContext (type = PersistenceContextType.EXTENDED) को यह बदल जाते हैं। फिर आप किसी भी जगह आलसी संपत्ति का उपयोग कर सकते हैं।

+1

यह तब तक सही नहीं है जब तक कि आप अपने लेन-देन को मैन्युअल रूप से प्रबंधित नहीं कर लेते। स्प्रिंग विस्तारित दृढ़ता संदर्भ प्रकार लंबे वार्तालाप पैटर्न के लिए है, ओपी के बारे में पूछे जाने वाले सत्र-प्रति-अनुरोध पैटर्न नहीं। – HDave

+0

मुझे लगता है कि @HDave सही है; यह भी देखें [लेनदेन-स्कोप्ड पर्सिस्टेंस संदर्भ और विस्तारित दृढ़ता संदर्भ के बीच क्या अंतर है?] (http://stackoverflow.com/questions/2547817/what-is-the-difference-between-transaction-scoped-persistence-context- और विस्तारित) – Arjan

2

आप lazy=false के प्रभाव के बारे में पता है और अभी भी चाहते हैं (जैसे प्रोटोटाइप प्रयोजनों के लिए) डिफ़ॉल्ट के रूप में करता है, तो आप के बाद किसी भी उपयोग कर सकते हैं:

  • अगर आप एक्सएमएल विन्यास का उपयोग कर रहे हैं: जोड़ने अपने इकाई वर्ग (ते)
11

मेरे लेख देखने के लिए @Proxy(lazy=false) जोड़ें: अपने <hibernate-mapping> तत्व

  • अगर आप एनोटेशन विन्यास का उपयोग कर रहे करने के लिए default-lazy="false"। LazyInitializationException - - मैं एक ही समस्या थी और यहाँ जवाब मैं अंत में के साथ आया है: स्थापना आलसी = false
    http://community.jboss.org/wiki/LazyInitializationExceptionovercome
    है इस सवाल का जवाब नहीं है - यह सब कुछ एक ही बार में लोड कर सकते हैं, और जरूरी है कि अच्छा नहीं है। उदाहरण:
    1 रिकॉर्ड तालिका एक संदर्भ:
    5 रिकॉर्ड तालिका बी संदर्भ:
    25 रिकॉर्ड तालिका सी संदर्भ:
    125 रिकॉर्ड तालिका डी
    ...
    आदि यह वह जगह है लेकिन क्या जा सकते हैं का एक उदाहरण गलत।
    --Tim साबिन

  • +0

    आपको यहां समाधान की व्याख्या करनी चाहिए, किसी तीसरे पक्ष की वेबसाइट से लिंक नहीं होना चाहिए .. –

    1

    आलसी क्षेत्र के लिए उपयोग Hibernate.initialize

    2

    यह केवल आपके डीएओ सत्र का उपयोग कर रहे हैं। इस प्रकार एक नया सत्र खुला है, फिर प्रत्येक कॉल के लिए डीएओ विधि में बंद करें।

    // open a session, get the number of entity and close the session 
    int startingCount = sfdao.count(); 
    
    // open a session, create a new entity and close the session 
    sfdao.create(sf); 
    
    // open a session, read an entity and close the session 
    SecurityFiling sf2 = sfdao.read(sf.getId()); 
    
    // open a session, delete an entity and close the session 
    sfdao.delete(sf); 
    
    etc... 
    

    डिफ़ॉल्ट, संग्रह और एक इकाई में एसोसिएशन द्वारा आलसी हैं: वे मांग पर डेटाबेस से लोड किए गए हैं इस प्रकार कार्यक्रम के निष्पादन के रूप में फिर से शुरू किया जा सकता है।इस प्रकार:

    sf.getSfSubmissionType().equals(sf2.getSfSubmissionType())

    एक अपवाद फेंक जाता है क्योंकि यह डेटाबेस से एक नया लदान का अनुरोध, और इकाई की लोडिंग के साथ जुड़े सत्र पहले से ही बंद कर दिया गया।

    • संलग्न हमारे सभी कोड के लिए एक सत्र बनाने:

      इस समस्या को हल करने के लिए दो दृष्टिकोण नहीं है। इस प्रकार इसका मतलब दूसरे सत्र को खोलने से बचने के लिए आपकी डीएओ सामग्री को बदलना होगा

    • एक सत्र बनाएं, फिर सम्मिलन से पहले इस सत्र में अपनी इकाई को अपडेट करें (यानी पुनः कनेक्ट करें)।

      session.update (ऑब्जेक्ट);

    0

    डिफ़ॉल्ट रूप से, सभी one-to-many और many-to-many संघों पहली बार के लिए एक्सेस किए जा रहे पर lazily दिलवाया जाता है।

    transactionTemplate.execute(new TransactionCallback<Void>() { 
        @Override 
        public Void doInTransaction(TransactionStatus transactionStatus) { 
    
         int startingCount = sfdao.count(); 
    
         sfdao.create(sf); 
    
         SecurityFiling sf2 = sfdao.read(sf.getId()); 
    
         sfdao.delete(sf); 
    
         int endingCount = sfdao.count(); 
    
         assertTrue(startingCount == endingCount); 
         assertTrue(sf.getId().longValue() == sf2.getId().longValue()); 
         assertTrue(sf.getSfSubmissionType().equals(sf2.getSfSubmissionType())); 
         assertTrue(sf.getSfTransactionNumber().equals(sf2.getSfTransactionNumber())); 
    
         return null; 
        } 
    }); 
    

    एक अन्य विकल्प अपने इकाई लोड हो रहा है पर सभी आलसी संघों लाने के लिए है, कि इतने:

    आपके उपयोग के मामले में, आप एक तार्किक सौदे में सभी डीएओ आपरेशन लपेटकर द्वारा इस मुद्दे पर काबू पाने सकता है

    SecurityFiling sf2 = sfdao.read(sf.getId()); 
    

    बहुत आलसी submissionType लाने चाहिए:

    select sf 
    from SecurityFiling sf 
    left join fetch.sf.submissionType 
    

    इस तरह, आप उत्सुकतापूर्वक सभी आलसी गुण प्राप्त करते हैं और सत्र भी बंद होने के बाद आप उन्हें एक्सेस कर सकते हैं।

    आप [one|many]-to-one एसोसिएशन और एक "[एक | कई] -to-many" सूची संघों (कार्टेशियन उत्पाद चलाने की वजह से) ला सकते हैं।

    एकाधिक "[एक | कई] -to-many" आरंभ करने के लिए, आपको अपनी रूट इकाई लोड करने के ठीक बाद Hibernate.initialize(collection) का उपयोग करना चाहिए।

    1

    आप स्प्रिंग और जेपीए एनोटेशन, आलसी इनिशियलाइज़ में सत्र के साथ समस्या से बचने के लिए simpliest रास्ता का उपयोग कर replaysing है:

    @PersistenceContext 
    

    @PersistenceContext(type = PersistenceContextType.EXTENDED) 
    
    +1

    यह केवल तभी काम करता है जब आप अपने लेन-देन को मैन्युअल रूप से प्रबंधित कर रहे हों – Gemasoft

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