आप जिस समस्या का प्रयोग कर रहे हैं, वह HINT_PASS_DISTINCT_THROUGH
का उपयोग करने के तरीके से संबंधित है। संकेत।
यह संकेत आपको हाइबरनेट को इंगित करने की अनुमति देता है कि DISTINCT
SELECT
. में कीवर्ड का इस्तेमाल नहीं करना चाहिए डेटाबेस के खिलाफ जारी बयान।
आप इस तथ्य का लाभ उठा रहे हैं ताकि आपके प्रश्नों को एक ऐसे क्षेत्र द्वारा क्रमबद्ध किया जा सके जो DISTINCT
में शामिल नहीं है। कॉलम सूची।
लेकिन ऐसा नहीं है कि इस संकेत का उपयोग कैसे किया जाना चाहिए।
इस संकेत का उपयोग केवल तभी किया जाना चाहिए जब आप सुनिश्चित हों कि DISTINCT
को लागू करने या न करने के बीच कोई अंतर नहीं होगा SQL के लिए कीवर्ड SELECT
कथन, क्योंकि SELECT
स्टेटमेंट पहले से ही सभी अलग-अलग मान प्रति से प्राप्त करेगा . विचार अनावश्यक DISTINCT
. के उपयोग से बचने के लिए क्वेरी के प्रदर्शन में सुधार करना है बयान।
आमतौर पर ऐसा तब होता है जब आप query.distinct
. का उपयोग करते हैं आप मानदंड प्रश्नों में विधि, और आप join fetching
. हैं बाल संबंध। यह बेहतरीन लेख
@VladMihalcea के बारे में विस्तार से बताएं कि संकेत कैसे काम करता है।
दूसरी ओर, जब आप पेजिंग का उपयोग करते हैं, तो यह OFFSET
सेट करेगा और LIMIT
- या कुछ इसी तरह, अंतर्निहित डेटाबेस के आधार पर - SQL में SELECT
डेटाबेस के खिलाफ जारी किया गया बयान, आपकी क्वेरी के परिणामों की अधिकतम संख्या तक सीमित है।
जैसा बताया गया है, यदि आप HINT_PASS_DISTINCT_THROUGH
का उपयोग करते हैं संकेत, SELECT
स्टेटमेंट में DISTINCT
नहीं होगा कीवर्ड और, आपके जुड़ने के कारण, यह संभावित रूप से आपकी मुख्य इकाई के डुप्लिकेट रिकॉर्ड दे सकता है। इस रिकॉर्ड को हाइबरनेट द्वारा डुप्लिकेट में अंतर करने के लिए संसाधित किया जाएगा, क्योंकि आप query.distinct
का उपयोग कर रहे हैं , और यह वास्तव में जरूरत पड़ने पर डुप्लिकेट को हटा देगा। मुझे लगता है कि यही कारण है कि आपको अपने Pageable
. में अनुरोध की तुलना में कम रिकॉर्ड मिल सकते हैं ।
यदि आप संकेत हटाते हैं, तो DISTINCT
. के रूप में कीवर्ड को SQL स्टेटमेंट में पास किया जाता है जो डेटाबेस को भेजा जाता है, जहाँ तक आप केवल मुख्य इकाई की जानकारी प्रोजेक्ट करते हैं, यह LIMIT
द्वारा इंगित सभी रिकॉर्ड प्राप्त करेगा। और यही कारण है कि यह आपको हमेशा अनुरोधित रिकॉर्ड की संख्या देगा।
आप कोशिश कर सकते हैं और fetch join
आपकी चाइल्ड इकाइयाँ (केवल join
. के बजाय उनके साथ)। यह DISTINCT
के कॉलम में आपके द्वारा सॉर्ट किए जाने वाले फ़ील्ड का उपयोग न कर पाने की समस्या को समाप्त कर देगा कीवर्ड और, इसके अलावा, आप अब वैध रूप से, संकेत को लागू करने में सक्षम होंगे।
लेकिन अगर आप ऐसा करते हैं तो यह आपको एक और समस्या होगी:यदि आप मुख्य संस्थाओं और उसके संग्रहों को वापस करने के लिए जॉइन फ़ेच और पेजिनेशन का उपयोग करते हैं, तो हाइबरनेट अब डेटाबेस स्तर पर पेजिनेशन लागू नहीं करेगा - इसमें OFFSET
शामिल नहीं होगा या LIMIT
SQL कथन में कीवर्ड, और यह परिणामों को स्मृति में पृष्ठांकित करने का प्रयास करेगा। यह प्रसिद्ध हाइबरनेट है HHH000104
चेतावनी:
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
@VladMihalcea इस के अंतिम भाग में विस्तार से बताते हैं कि लेख।
उन्होंने आपकी समस्या का एक संभावित समाधान भी प्रस्तावित किया, Window Functions ।
Specification
. का उपयोग करने के बजाय आप मामले का उपयोग करते हैं s, विचार यह है कि आप अपना स्वयं का DAO लागू करते हैं। इस डीएओ को केवल EntityManager
. तक पहुंच की आवश्यकता है , जो कोई बड़ी बात नहीं है क्योंकि आप अपने @PersistenceContext
. को इंजेक्ट कर सकते हैं :
@PersistenceContext
protected EntityManager em;
एक बार आपके पास यह EntityManager
हो जाए , आप दिए गए Pageable
. के आधार पर, स्थानीय क्वेरी बना सकते हैं और निर्माण के लिए विंडो फ़ंक्शन का उपयोग कर सकते हैं जानकारी, सही SQL कथन जो डेटाबेस के विरुद्ध जारी किया जाएगा। यह आपको इस बारे में बहुत अधिक स्वतंत्रता देगा कि कौन से फ़ील्ड छँटाई के लिए उपयोग करते हैं या जो भी आपको चाहिए।
जैसा कि अंतिम उद्धृत लेख इंगित करता है, विंडो फ़ंक्शंस सभी मेयर डेटाबेस द्वारा समर्थित एक विशेषता है।
PostgreSQL के मामले में, आप उन्हें आधिकारिक दस्तावेज़ों में आसानी से देख सकते हैंए> ।
अंत में, एक और विकल्प, वास्तव में @nickshoe द्वारा सुझाया गया है, और लेख उन्होंने उद्धृत किया, छँटाई और पेजिंग प्रक्रिया को दो चरणों में करना है:पहले चरण में, आपको एक क्वेरी बनाने की आवश्यकता है जो आपके बच्चे की संस्थाओं को संदर्भित करेगी और जिसमें आप पेजिंग और सॉर्टिंग लागू करेंगे। यह क्वेरी आपको मुख्य संस्थाओं की आईडी की पहचान करने की अनुमति देगी, जिनका उपयोग प्रक्रिया के दूसरे चरण में, मुख्य संस्थाओं को स्वयं प्राप्त करने के लिए किया जाएगा।
इस प्रक्रिया को पूरा करने के लिए आप उपरोक्त कस्टम डीएओ का लाभ उठा सकते हैं।