2012-10-09 19 views
6

की ओर जाता है मेरे पास लिंक तालिका में एक अतिरिक्त कॉलम के साथ कई से अधिक संबंध हैं। मैंने इसे इस तरह से कॉन्फ़िगर किया है कि स्वामित्व वाली पक्ष बच्चों को उत्सुक बनाती है (इसलिए मुझे LazyInitializationException नहीं मिलता है) और विपरीत दिशा में यह आलसी है। यह काम।@ ट्रांसेक्शनल (readOnly = true) LazyInitializationException

मैं अब फ़ाइन-ट्यून करने के लिए लेन-देन (से पहले वहाँ डीएओ और सेवा वर्गों के वर्ग स्तर पर सिर्फ @Transactional चाहता था मैं readOnly = true को विधि getById सेट:।

@Transactional(readOnly = true) 
public Compound getById(Long id) { 
    return compoundDAO.getById(id); 
} 

इस बदलाव के बाद मैं एक LazyInitializationException में मिलता है निम्नलिखित स्निपेट:

Compound compound = compoundService.getById(6L);   
Structure structure = compound.getComposition().get(0).getStructure(); 
System.out.println("StructureId: "+ structure.getId()); // LazyInitializationException 

अगर मैं (readOnly = true) इस काम करता है को दूर किसी को भी इस व्यवहार की व्याख्या कर सकते मैं वसंत + हाइबरनेट भ्रामक का प्रकार का उपयोग के रूप में मैं किसी भी कारण है कि वें नहीं दिख रहा है!?। क्या डेटा को लोड किया जाना चाहिए?


संपादित करें:

संबंध परिभाषाओं की

स्निपेट्स। यह लिंक तालिका में एक कॉलम के साथ कई से अधिक है।

मालिक पक्ष (जैसे यौगिक संरचनाएं शामिल हैं):

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.structure", 
cascade = CascadeType.ALL) 
@OrderBy("pk.compound.id ASC") 
private List<CompoundComposition> occurence; 

कई-टू-वन @Embeddable आईडी वर्ग

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Compound getCompound() { 
    return compound; 
} 

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Structure getStructure() { 
    return structure; 
} 

संपादित 2 में:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.compound", 
    cascade = CascadeType.ALL, orphanRemoval = true) 
@OrderBy("pk.structure.id ASC") 
private List<CompoundComposition> composition = new ArrayList<>(); 

पक्ष से संबंध रखता है :

सेंट एसीके ट्रेस

org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:272) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.bitbucket.myName.myApp.entity.Structure_$$_javassist_0.getId(Structure_$$_javassist_0.java) ~[classes/:na] 
    at org.bitbucket.myName.myApp.App.main(App.java:31) ~[classes/:na] 

संपादित करें 3:

लॉग केवल पढ़ने के साथ बहुत अलग है और यह याद आ रही है हिस्सा थे संबंधों लोड किए गए हैं, जैसे:

इसके अलावा मेरी टिप्पणी देखें। लॉग में कुछ चयन गायब हैं।

संपादित करें 4:

तो मैं एक बुनियादी DriverManagerDataSource और कोई कनेक्शन पूल के साथ थक गया। मुद्दा बिल्कुल वही है। मेरे लिए हाइबरनेट में एक समस्या की तरह दिखता है।

+0

कक्षा स्तर की लेनदेन परिभाषा क्या है? –

+0

बस @ ट्रांसेक्शनल। –

+0

क्या आप मॉडल कक्षाओं के स्निपेट पोस्ट कर सकते हैं? और, क्या आपके पास अभी भी डीएओ कक्षा के शीर्ष पर '@ ट्रांजेक्शनल 'एनोटेशन है? – sbzoom

उत्तर

3

यह सिर्फ वाह है। मुझे समझना शुरू हो रहा है कि क्यों कुछ लोग ओआरएम से नफरत करते हैं ... बस ऐसा लगता है कि मुझे लगातार अजीब मुद्दे को हल करने के लिए घंटों खर्च करना पड़ता है और समाधान एनोटेशन का एक बहुत ही विशिष्ट सेट है + कुछ कोड कहा गया सीमाओं के आसपास काम करने के लिए एनोटेशन।

सबसे पहले ऐसा क्यों होता है (जिसका अर्थ है एनोटेशन, लेकिन तार्किक अर्थ बनाने के मामले में, जो सामान्य ज्ञान का उपयोग करने के रूप में यहां वास्तविक समस्या बेकार है। केवल परीक्षण और त्रुटि मदद करता है)। स्वामित्व में, @OneToMany में मेरे पास orphanRemoval = true है (जिसे मैंने पाया है स्थिरता के लिए आवश्यक है। कोई सोचता है कि डेटाबेस की बाधाओं को इसे संभालना चाहिए ... केवल उन चीजों में से एक जो आपको पागल कर सकते हैं।)। ऐसा लगता है कि अगर लेनदेन केवल पढ़ने के लिए नहीं है, तो इस सेटिंग को कुछ डेटा प्राप्त किए गए अपने आलसी, अर्थात् यहाँ तो भी किया जा रहा है की ओर जाता है:

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Structure getStructure() { 
    return structure; 
} 

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

तो स्पष्ट समाधान FetchType.EAGER में बदलने के लिए उपरोक्त संबंध में होगा। गलत! यदि आप ऐसा करते हैं तो आप session.merge का उपयोग करके स्वामित्व पक्ष (कंपाउंड) को अपडेट नहीं कर पाएंगे। यह एक StackOverFlowError के लिए नेतृत्व करेंगे।

असली समाधान वास्तव में पहले से ही उल्लेख किया गया था। बस config छोड़ के रूप में है, लेकिन स्पष्ट रूप से सेवा परत में वांछित संबंधों लोड:

@Transactional(readOnly = true) 
@Override  
public Compound getById(Long id) { 

    Compound compound = compoundDAO.getById(id); 
    for (CompoundComposition composition : compound.getComposition()){ 
     Hibernate.initialize(composition.getStructure()); 
    }   
    return compound; 
} 

मैं मानता हूं मैं समय से पहले अनुकूलन जाल में गिर करने के लिए प्रवृत्त कर रहा हूँ। यह बहुत ही कुशल नहीं दिखता है और यह भी लगता है कि एसक्यूएल पहली जगह कैसे काम करता है। लेकिन फिर मैं भाग्यशाली स्थिति में हूं कि ज्यादातर मामलों में कंपाउंड कॉम्पोजिशन में केवल 1 या 2 तत्व होंगे।

+1

आपके पहले दो पैराग्राफ 6-या-इतने सालों तक हैं जो मैंने हाइबरनेट/जेपीए/ओआरएम के साथ बिताए थे। – millhouse

0

शायद आप, getById() विधि के शरीर में

value.getComposition().get(i).getStructure(); 

डाल सकता है इतना है कि आलसी लोड हो रहा है लेन-देन में होता है। मुझे इस मामले में एहसास है कि आपको i पर लूप करना होगा जो असुविधाजनक हो सकता है।

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