JPA और Hibernate का उपयोग करते समय JOIN और JOIN FETCH में क्या अंतर है


183

कृपया मुझे यह समझने में मदद करें कि एक नियमित जॉइन का उपयोग कहां करना है और कहां शामिल है।

उदाहरण के लिए, यदि हमारे पास ये दो प्रश्न हैं

FROM Employee emp
JOIN emp.department dep

तथा

FROM Employee emp
JOIN FETCH emp.department dep

क्या उनके बीच कोई अंतर है? यदि हाँ, तो कब कौन सा उपयोग करना है?


2
आप इसे यहां पढ़ सकते हैं लिंक 14.3
Angga

4
मैं उस डॉक्यूमेंटेशन से गुज़रा हूं, लेकिन अभी भी नहीं जानता कि मुझे एक JOIN और एक JOIN FETCH का उपयोग कहाँ करना चाहिए।
अब्बास 20

2
यदि आपके पास FetoneType.LAZY पर @oneToOne मैपिंग सेट है और आप दूसरी क्वेरी का उपयोग करते हैं (क्योंकि आपको कर्मचारी वस्तुओं के भाग के रूप में विभाग की वस्तुओं को लोड करने की आवश्यकता है) हाइबरनेट क्या करेगा, यह प्रत्येक व्यक्ति के लिए विभाग की वस्तुओं को लाने के लिए प्रश्न जारी करेगा कर्मचारी वस्तु यह DB से प्राप्त होता है। बाद में कोड में आप विभाग की वस्तुओं को कर्मचारी के माध्यम से विभाग-एकल संघ में ले सकते हैं और हाइबरनेट दिए गए कर्मचारी के लिए विभाग की वस्तु लाने के लिए कोई क्वेरी जारी नहीं करेंगे। याद रखें कि हाइबरनेट अभी भी अपने द्वारा प्राप्त किए गए कर्मचारियों की संख्या के बराबर प्रश्न जारी करता है।
बंटी

डॉक हंट में मदद करने के लिए ~ फ़ेचिंग रणनीतियाँ
एडी बी

1
@ शेमेराअनुरंगा मुझे लगता है कि इस मामले में आपको एक लेफ्टिनेंट मास्टर की आवश्यकता होगी।
अब्बास

जवाबों:


181

इस दो प्रश्नों में, आप JOIN का उपयोग उन सभी कर्मचारियों को क्वेरी करने के लिए कर रहे हैं जिनके पास कम से कम एक विभाग संबद्ध है।

लेकिन, अंतर यह है: पहली क्वेरी में आप हाइबरनेट के लिए केवल कर्मचारी को वापस कर रहे हैं। दूसरी क्वेरी में, आप कर्मचारी और संबद्ध सभी विभाग लौटा रहे हैं ।

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

आप दूसरी क्वेरी का उपयोग तब कर सकते हैं जब आप सुनिश्चित करें कि आपको प्रत्येक कर्मचारी के विभाग की आवश्यकता होगी। यदि आपको विभाग की आवश्यकता नहीं है, तो पहले क्वेरी का उपयोग करें।

यदि आप कुछ शर्त (जहां आपको शायद जरूरत पड़ेगी) लागू करने की आवश्यकता है: मैं इस लिंक को फिर से पढ़ता हूं: जेपीक्यूएल को "जेपी 2 क्राइटेरियाएक्यू" के रूप में "कहाँ" के साथ "सम्मिलित हों" को ठीक से कैसे व्यक्त करें?

अपडेट करें

यदि आप उपयोग नहीं करते हैं fetchऔर विभाग लौटाए जाते हैं, तो इसका कारण यह है कि कर्मचारी और विभाग (क @OneToMany) के बीच आपकी मैपिंग के साथ समझौता कर लिया जाता है FetchType.EAGER। इस स्थिति में, कोई भी HQL (साथ fetchया नहीं) क्वेरी के साथ FROM Employeeसभी विभाग लाएगा। याद रखें कि सभी मैपिंग * ToOne ( @ManyToOneऔर @OneToOne) डिफ़ॉल्ट रूप से EAGER हैं।


1
यदि हम बिना विवरण प्राप्त किए और परिणाम प्राप्त करते हैं तो कौन सा व्यवहार होगा। फिर सत्र के भीतर हम विभाग के लिए इलाज करेंगे?
gstackoverflow

1
@gstackoverflow, हाँ
धेरिक

मैं संबंध के दोनों पक्षों में आलसी भ्रूण के साथ देशी क्वेरी का उपयोग करता हूं, लेकिन फिर भी बाल संबंधों के पदानुक्रम को लोड करता है।
बादामची

वर्थ उल्लेख है कि fetchअगर (हमारे उदाहरण का उपयोग करके) आप किसी विभाग विशेषता द्वारा ऑर्डर करना चाहते हैं तो इसका उपयोग करना होगा। अन्यथा, (कम से कम पीजी के लिए मान्य) आपको मिल सकता हैERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
लंबी

60

में इस लिंक मैं टिप्पणी पर कि पहले उल्लेख किया, इस भाग पढ़ें:

एक "लाने" में शामिल होने या एक ही चयन का उपयोग करके अपने माता-पिता की वस्तुओं के साथ मूल्यों के संग्रह को आरंभ करने की अनुमति देता है। संग्रह के मामले में यह विशेष रूप से उपयोगी है। यह प्रभावी रूप से संघों और संग्रह के लिए मैपिंग फ़ाइल के बाहरी जुड़ाव और आलसी घोषणाओं को ओवरराइड करता है

यह "JOET FETCH" आपके पास (संग्रह = FetchType.LAZY) प्रॉपर्टी के अंदर इकाई (उदाहरण bellow) के लिए एक प्रॉपर्टी है तो इसका प्रभाव पड़ेगा।

और यह "जब क्वेरी होनी चाहिए" की विधि का ही प्रभाव है। और तुम भी पता होना चाहिए कि यह :

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

जब एसोसिएशन लाया जाता है -> आपका "FETCH" प्रकार

यह कैसे लाया जाता है -> ज्वाइन / सलेक्ट / सबसेक्ट / बैच

आपके मामले में, FETCH का केवल तभी प्रभाव होगा जब आपके पास कर्मचारी के अंदर एक विभाग के रूप में विभाग में कुछ इस तरह हो:

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

जब आप का उपयोग करें

FROM Employee emp
JOIN FETCH emp.department dep

आप मिल जाएगा empऔर emp.dep। जब आप भ्रूण का उपयोग नहीं करते हैं, तब भी आप प्राप्त कर सकते हैं, emp.depलेकिन विभाग के उस सेट को प्राप्त करने के लिए हाइबरनेट डेटाबेस के लिए किसी अन्य चयन को संसाधित करेगा।

इसलिए यह सिर्फ एक प्रदर्शन ट्यूनिंग की बात है, जिसके बारे में आप एक ही क्वेरी (उत्सुक लाने) में सभी परिणाम प्राप्त करना चाहते हैं (आपको इसकी आवश्यकता है या नहीं), या आप इसे बाद में क्वेरी करना चाहते हैं जब आपको इसकी आवश्यकता होती है (आलसी लाने)।

जब आपको एक चयन (एक बड़ी क्वेरी) के साथ छोटे डेटा प्राप्त करने की आवश्यकता हो, तो उत्सुकता का उपयोग करें। या आलसी लाने के लिए क्वेरी का उपयोग करें जिसे आपको बाद की आवश्यकता है (कई छोटी क्वेरी)।

जब उपयोग करें:

  • कोई बड़ा गैर- संग्रहित संग्रह / उस इकाई के अंदर सेट नहीं है जिसे आप प्राप्त करने वाले हैं

  • अनुप्रयोग सर्वर से डेटाबेस सर्वर तक संचार बहुत दूर है और लंबे समय की आवश्यकता है

  • आप इसका उपयोग (नहीं है जब आप उस संग्रह उत्तरार्द्ध आवश्यकता हो सकती है बाहर का लेन-देन संबंधी विधि / वर्ग)


क्या आप इसे उन प्रश्नों के लिए समझा सकते हैं जो मैंने अभी अद्यतन प्रश्न में लिखे थे।
abbas

उपयोगी विचार: "कोई बड़ा गैर-संग्रहित संग्रह / उस इकाई के अंदर सेट जो आपको मिलने वाला है"
Divs

क्या विभागों में अभी भी उत्सुकता होगी अगर कर्मचारी के अंदर के विभाग Listइसके बजाय थे Set?
स्टीफन

क्या FETCHJPQL स्टेटमेंट में कीवर्ड का उपयोग करना एक उत्सुकता से प्राप्त संपत्ति है?
स्टीफन

15

शामिल हों

JOINएक इकाई संघों के खिलाफ उपयोग करते समय , जेपीए जनरेट किए गए SQL स्टेटमेंट में मूल इकाई और चाइल्ड एंटिटी टेबल के बीच एक JOIN उत्पन्न करेगा।

इस उदाहरण को लेते समय, इस JPQL क्वेरी को निष्पादित करते समय:

FROM Employee emp
JOIN emp.department dep

हाइबरनेट निम्नलिखित SQL कथन उत्पन्न करने जा रहा है:

SELECT emp.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

ध्यान दें कि SQL SELECTक्लॉज़ में केवल employeeटेबल कॉलम होते हैं, और न कि departmentवाले। departmentटेबल कॉलम लाने के लिए , हमें JOIN FETCHइसके बजाय उपयोग करने की आवश्यकता है JOIN

फिट बैठो

तो, की तुलना में JOIN, JOIN FETCHआप SELECTउत्पन्न SQL कथन के खंड में शामिल होने वाले टेबल कॉलम को प्रोजेक्ट करने की अनुमति देता है ।

इसलिए, आपके उदाहरण में, इस JPQL क्वेरी को निष्पादित करते समय:

FROM Employee emp
JOIN FETCH emp.department dep

हाइबरनेट निम्नलिखित SQL कथन उत्पन्न करने जा रहा है:

SELECT emp.*, dept.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

ध्यान दें, इस बार, जेपीएनसी क्लॉज departmentमें सूचीबद्ध इकाई से जुड़े न केवल टेबल कॉलम को चुना गया है FROM

इसके अलावा, हाइबरनेट का उपयोग JOIN FETCHकरते LazyInitializationExceptionसमय संबोधित करने का एक शानदार तरीका है क्योंकि आप FetchType.LAZYमुख्य इकाई के साथ-साथ आपके द्वारा प्राप्त की जा रही फ़िशिंग रणनीति का उपयोग करके इकाई संघों को आरंभ कर सकते हैं।


क्या एक ही क्वेरी में कई JOIN FETCH का उपयोग करना संभव है?
.ऑनूर Janzcan

2
आप कई कई-से-एक और एक-से-एक संघ और अधिकतम एक संग्रह में शामिल हो सकते हैं। कई संग्रह प्राप्त करना, जैसे एक-से-एक या कई-से-कई संघ कार्टेशियन उत्पाद में समाप्त हो जाएंगे । हालाँकि, यदि आप कई संग्रह प्राप्त करना चाहते हैं, तो आप द्वितीय, तृतीय, ..., nth संग्रह के लिए द्वितीयक प्रश्नों का उपयोग कर सकते हैं। की जाँच करें इस लेख अधिक जानकारी के लिए।
व्लाद मिहालसी

5

यदि आपके पास @oneToOneमैपिंग सेट है FetchType.LAZYऔर आप दूसरी क्वेरी का उपयोग करते हैं (क्योंकि आपको कर्मचारी वस्तुओं के भाग के रूप में लोड होने के लिए विभाग की वस्तुओं की आवश्यकता है) हाइबरनेट क्या करेगा, तो यह प्रत्येक व्यक्ति के लिए विभाग की वस्तुओं को लाने के लिए क्वेरीज़ जारी करेगा, जो डीबी से प्राप्त होता है।

बाद में, कोड में आप विभाग की वस्तुओं को कर्मचारी के माध्यम से विभाग की एकल-मूल्यवान एसोसिएशन तक पहुँचा सकते हैं और हाइबरनेट दिए गए कर्मचारी के लिए विभाग की वस्तु लाने के लिए कोई क्वेरी जारी नहीं करेंगे।

याद रखें, हाइबरनेट अभी भी जारी किए गए कर्मचारियों की संख्या के बराबर प्रश्न जारी करता है। यदि आप सभी कर्मचारी वस्तुओं के विभाग की वस्तुओं का उपयोग करना चाहते हैं, तो हाइबरनेट उपरोक्त दोनों प्रश्नों में समान प्रश्नों को जारी करेगा


2

धेरिक: मैं इस बारे में निश्चित नहीं हूं कि आप क्या कहते हैं, जब आप इसका उपयोग नहीं करते हैं तो परिणाम प्रकार का होगा: List<Object[ ]>जिसका अर्थ है ऑब्जेक्ट टेबल की सूची और कर्मचारी की सूची नहीं।

Object[0] refers an Employee entity 
Object[1] refers a Departement entity 

जब आप भ्रूण का उपयोग करते हैं, तो बस एक ही चयन होता है और परिणाम कर्मचारी List<Employee>की सूची है जिसमें प्रस्थान की सूची होती है। यह इकाई की आलसी घोषणा को ओवरराइड करता है।


मुझे नहीं पता कि मैं आपकी चिंता को समझता हूं। यदि आप उपयोग नहीं करते हैं fetch, तो आपकी क्वेरी केवल कर्मचारी वापस कर देंगे। यदि विभाग, यहां तक ​​कि इस मामले में, लौटाया जाना जारी है, क्योंकि कर्मचारी और विभाग (एक @OneToMany) के बीच आपकी मैपिंग FetTType.EAGER के साथ तय की जाती है। इस स्थिति में, कोई भी HQL (साथ fetchया नहीं) क्वेरी के साथ FROM Employeeसभी विभाग लाएगा।
धेरिक

भ्रूण का उपयोग किए बिना (केवल शब्द से जुड़ें), परिणाम संग्रह की एक सरणी होगी, दो पंक्तियाँ, पहला कर्मचारी का एक संग्रह है और दूसरा विभागों का संग्रह है। उत्सुक भ्रूण या आलसी भ्रूण का उपयोग करके, विभागों को लाया जाएगा।
बिलाल बीबीबी

HQL पर लाने के बिना, यह केवल तभी होगा जब कर्मचारी और विभाग के बीच आपकी मैपिंग EAGER ( @OneToMany(fetch = FetchType.EAGER) हो। यदि ऐसा नहीं है, तो विभाग वापस नहीं किए जाएंगे।
धेरिक

@Dherik इसे स्वयं आज़माएँ, आपको एक ClassCastException मिल जाएगी।
बिलाल बीबीबी

मैं समस्या का पता लगाता हूं। एक भ्रूण की समस्या नहीं है, लेकिन selectएचक्यूएल में कैसे बनाया गया था। कोशिश करो SELECT emp FROM Employee emp JOIN FETCH emp.department dep। JPA / हाइबरनेट का यह व्यवहार वापसी Listका है Object[]जब आप SELECTभाग को छोड़ते हैं ।
धेरिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.