2012-11-14 9 views
5

मेरे समस्या यह है कि हाइबरनेट OneToOne संघ के उत्सुक लोड हो रहा है पर अमल +1 प्रत्येक अशक्त संबंध के लिए चयन है।हाइबरनेट OneToOne (वैकल्पिक = true) FetchMode.JOIN साथ पुन: चुनें करने के लिए अशक्त कोशिश महत्व देता

इकाई उदाहरण:

@Entity 
class SideBlue { 
    @Column(nullable = false) 
    private Integer timestamp; 

    @OneToOne(optional=true) 
    @JoinColumn(name="timestamp", referenceColumn="timestamp", insertable = false, updatable = false) 
    SideRed redSide; 
} 
@Entity 
class SideRed { 
    @Column(nullable = false) 
    private Integer timestamp; 
} 

(यह एक विरासत डेटाबेस स्कीमा है, तो डेटाबेस संशोधनों अनुमति नहीं है)

क्वेरी उदाहरण:

CriteriaBuilder builder... CriteriaQuery query... 
Root<SideBlue> root = query.from(SideBlue.class); 
root.fetch(SideBlue_.sideRed, JoinType.LEFT); 
entityManager().createQuery(query).getResultList(); 

परिणाम: यदि सब नीले पक्ष संस्थाओं एक लाल ओर सब कुछ सही ढंग से चला जाता है है,, इसलिए केवल डेटाबेस जो भी के लिए संस्थाओं को पुनः प्राप्त हो जाएगा करने के लिए एक क्वेरी निष्पादित हाइबरनेट।

लेकिन, अगर नीले पक्ष संस्थाओं जुड़े कोई लाल पक्ष इकाई है, दूसरी तरफ एक बार और पता लगाने की कोशिश हाइबरनेट। हाइबरनेट एसक्यूएल टिप्पणी कहती है '/ * लोड लालसाइड */चुनें ...' प्रत्येक शून्य लालसा संपत्ति के लिए।

मैं कैसे छोड़ इस दूसरे का चयन कर सकते हैं?

व्यावहारिक समस्या प्रकट होता है जब विलंबता बेहद कम नहीं है। यदि मैं 1 मिलियन पंक्तियों का चयन करने की कोशिश करता हूं, और 1/3 में शून्य 'लाल पक्ष' हैं, तो कुल विलंबता एक वास्तविक समस्या है।

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

इस क्वेरी

10:04:32.812 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0 
10:04:32.815 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[SideBlue#1269721], EntityKey[SideRed#3620564] 
10:04:32.833 [main] DEBUG org.hibernate.loader.Loader - Result set row: 1 
10:04:32.833 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[SideBlue#1269776], null 

पहली पंक्ति नीले और लाल पक्षों शामिल है, लेकिन दूसरा एक ही नीले पक्ष के लिए डीबग लॉग है। तो हाइबरनेट को पता होना चाहिए कि संबंधित लाल पक्ष मौजूद नहीं है। लेकिन, के बाद सभी परिणाम पंक्तियां संसाधित कर रहे हैं ...

10:04:33.083 [main] DEBUG o.h.engine.internal.TwoPhaseLoad - Resolving associations for [BlueSide#1269721] 
10:04:33.084 [main] DEBUG org.hibernate.loader.Loader - Loading entity: [RedSide#component[timestamp]{timestamp=1338937390}] 
10:04:33.084 [main] DEBUG org.hibernate.SQL - /* load RedSide */ select ... 
! Nothing really loaded because the previous SQL return empty result set, again ! 
10:04:33.211 [main] DEBUG org.hibernate.loader.Loader - Done entity load 
+1

आपका उदाहरण उलझन में है, जिस पक्ष में @JoinColumn एनोटेशन है, उस संबंध के संबंध में परिभाषा के मालिक है। – Affe

+0

मेरी गलती। मैं इकाई परिभाषा को फिर से परिभाषित/सुधारता हूं। यह मेरी इकाई का सरलीकृत संस्करण है, लेकिन मुझे लगता है कि यह पर्याप्त है। डेटाबेस दोनों पक्षों के बीच कोई एफके नहीं है। –

उत्तर

0

ठीक है, आप SideRed लोड नहीं करने के लिए जब आप SideBlue के लिए एक प्रश्न करना कोशिश कर रहा। मुझे लगता है कि यह एक लेज़ी लोड हो रहा है समस्या यह है कि हाइबरनेट से (https://community.jboss.org/wiki/SomeExplanationsOnLazyLoadingone-to-one?_sscc=t से) इस "सीमा" के साथ संबंधित है:

class B { 
    private C cee; 

    public C getCee() { 
     return cee; 
    } 

    public void setCee(C cee) { 
     this.cee = cee; 
    } 
} 

class C { 
    // Not important really 
} 

सही बी लोड हो रहा है के बाद, आप सी प्राप्त लेकिन देखने के लिए getCee() कह सकते हैं, getCee() अपने वर्ग की एक विधि है और हाइबरनेट इस पर कोई नियंत्रण नहीं है। हाइबरनेट को पता नहीं है कि कोई व्यक्ति getCee() कहने जा रहा है। इसका मतलब है कि हाइबरनेट पल यह डेटाबेस से बी लोड करता है पर "CEE" संपत्ति में एक उचित मूल्य लगाना चाहिए।

प्रॉक्सी सी के लिए सक्षम है, तो हाइबरनेट एक सी प्रॉक्सी वस्तु जो अभी तक लोड नहीं है डाल सकते हैं, लेकिन जब कोई इसे इस्तेमाल करता है लोड किया जा होगा। यह एक-से-एक के लिए आलसी लोडिंग देता है।

लेकिन अब मान लें कि आपकी बी वस्तु हो सकता है या जुड़े सी (विवश = "false") नहीं हो सकता है। विशिष्ट बी में सी नहीं होने पर सीई() वापस आना चाहिए? शून्य। लेकिन याद रखें, हाइबरनेट पल यह बी सेट पर "CEE" की सही मान सेट करना होगा (क्योंकि यह कोई पता करता है जब कोई getCee फोन करेगा())। प्रॉक्सी यहाँ मदद नहीं करता है क्योंकि पहले से ही गैर-शून्य वस्तु में प्रॉक्सी ही।

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

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