समस्या का विवरण

जैसा कि हमने ऊपर कहा, LazyCollectionOption.EXTRA एनोटेशन में एक समस्या है - यह प्रत्येक ऑब्जेक्ट के लिए डेटाबेस के लिए एक अलग अनुरोध करता है। हमें किसी तरह हाइबरनेट को समझाने की जरूरत है कि हम चाहते हैं कि यह तुरंत हमारे मूल वस्तुओं के लिए सभी बाल वस्तुओं को लोड करे।

हाइबरनेट के डेवलपर्स इस समस्या के समाधान के साथ आए हैं, एचक्यूएल में जॉइन फ़ेच ऑपरेटर।

एचक्यूएल क्वेरी उदाहरण:

select distinct task from Task t left join fetch t.employee order by t.deadline

इस प्रश्न में, एक ही समय में सब कुछ सरल और जटिल है। आइए इसे टुकड़े-टुकड़े बनाने की कोशिश करें।

विकल्प 1

हम सभी वस्तुओं को डाउनलोड करना चाहते हैंकाम, समय सीमा के अनुसार क्रमबद्ध। यहाँ वह अनुरोध कैसा दिखेगा:

select task from Task t order by t.deadline

जबकि सबकुछ साफ है। लेकिन मैदानकर्मचारीटास्क क्लास में EXTRA एनोटेशन के साथ एनोटेट किए गए कर्मचारियों का संग्रह होगा । और इस संग्रह की वस्तुओं को लोड नहीं किया जाएगा।

विकल्प 2

किसी वस्तु के लिए बाल वस्तुओं को लोड करने के लिए हाइबरनेट को बाध्य करेंकाम.

select task from Task t join fetch t.employee order by t.deadline

मदद से, हम अपनी क्वेरी में कार्य और कर्मचारी संस्थाओं को स्पष्ट रूप से बाँधते हैं। हाइबरनेट पहले से ही यह जानता है क्योंकि हम इन क्षेत्रों में @ManyToMany एनोटेशन का उपयोग करते हैं।

लेकिन हमें एक जॉइन स्टेटमेंट प्राप्त करने के लिए इसे एक फ़ेच स्टेटमेंट के साथ पूरा करने के लिए एक जॉइन स्टेटमेंट की आवश्यकता होती है । इस प्रकार हम हाइबरनेट को बताते हैं कि जब हमारे अनुरोध को निष्पादित किया जाता है तो टास्क.कर्मचारी संग्रह में वस्तुओं को डेटाबेस से लोड करने की आवश्यकता होती है।

विकल्प 3

पिछले समाधान में कुछ बग हैं। सबसे पहले, ज्वाइन का उपयोग करने के बाद, SQL हमें ऑब्जेक्ट वापस नहीं करेगाकाम, जिनके साथ कर्मचारी तालिका में कोई वस्तु संबद्ध नहीं है। इनर जॉइन ठीक इसी तरह काम करता है ।

इसलिए हमें एक बाएं ऑपरेटर के साथ अपने जुड़ाव को बढ़ाने और इसे बाएं जोड़ में बदलने की जरूरत है । उदाहरण:

select task from Task t left join fetch t.employee order by t.deadline

विकल्प 4

लेकिन वह सब नहीं है। यदि आपके कोड में संस्थाओं के बीच संबंध कई-से-मई है, तो क्वेरी परिणामों में डुप्लिकेट होंगे। वही वस्तुकामविभिन्न कर्मचारियों (कर्मचारी वस्तुओं) पर पाया जा सकता है।

इसलिए डुप्लिकेट टास्क ऑब्जेक्ट से छुटकारा पाने के लिए आपको चुनिंदा शब्द के बाद विशिष्ट कीवर्ड जोड़ना होगा।

select distinct task from Task t left join fetch t.employee order by t.deadline

इस तरह 4 चरणों में हम उस अनुरोध पर पहुंचे जिसके साथ हमने शुरुआत की थी। खैर, जावा कोड काफी अपेक्षित लगेगा:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
return query.list();

Fetch सीमाओं में शामिल हों

कोई भी पूर्ण नहीं है। JOIN FETCH स्टेटमेंट भी। इसकी काफी कुछ सीमाएँ हैं। और पहले वाला setMaxResults() और setFirstResult() विधियों का उपयोग कर रहा है ।

JOIN FETCH स्टेटमेंट के लिए, हमारा हाइबरनेट एक बहुत ही जटिल क्वेरी उत्पन्न करेगा जिसमें हम तीन तालिकाओं को एक में जोड़ते हैं: कर्मचारी, कार्य और कर्मचारी_कार्य। वास्तव में, यह कर्मचारियों या कार्यों के लिए अनुरोध नहीं है, बल्कि सभी ज्ञात कर्मचारी-कार्य जोड़े के लिए है।

और SQL अपने LIMIT और OFFSET कथनों को ठीक उसी कर्मचारी-कार्य जोड़े की क्वेरी पर लागू कर सकता है। साथ ही, यह एचक्यूएल क्वेरी से स्पष्ट रूप से अनुसरण करता है कि हम वास्तव में कार्य (कार्य) प्राप्त करना चाहते हैं, और यदि हम अपने FirstResult और MaxResult पैरामीटर को पुनर्वितरित करते हैं, तो उन्हें विशेष रूप से कार्य वस्तुओं को संदर्भित करना चाहिए।

यदि आप इस तरह कोड लिखते हैं:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
       	    query.setFirstResult(0);
        	   query.setMaxResults(1);
return query.list();

फिर हाइबरनेट SQL क्वेरी के OFFSET और LIMIT पैरामीटर में FirstResult और MaxResult को सही ढंग से परिवर्तित करने में सक्षम नहीं होगा।

इसके बजाय, यह तीन काम करेगा:

  • SQL क्वेरी आम तौर पर तालिका से सभी डेटा का चयन करेगी और इसे हाइबरनेट पर वापस कर देगी
  • हाइबरनेट अपनी स्मृति में आवश्यक अभिलेखों का चयन करेगा और उन्हें आपको लौटा देगा
  • हाइबरनेट एक चेतावनी जारी करेगा

चेतावनी कुछ इस तरह होगी:

WARN [org.hibernate.hql.internal.ast.QueryTranslatorImpl] HHH000104: 
firstResult/maxResults specified with collection fetch; applying in memory!