2012-03-07 15 views
15

मैं हाइबरनेट के साथ काम कर रहा हूं और मुझे एक एचक्यूएल क्वेरी बनाने में परेशानी हो रही है जो मेरे ऑब्जेक्ट के सभी बच्चों को लाती है। उदाहरण के लिए: ऑब्जेक्ट उपयोगकर्ता की कारों की सूची और दोस्तों की एक सूची है।हाइबरनेट में कई बच्चों को लाने में कैसे शामिल हों?

अपनी कारों के साथ उपयोगकर्ता को प्राप्त करने के लिए मैं निम्नलिखित क्वेरी का उपयोग करूंगा:
उपयोगकर्ता से आप यू.यू.एस. लाने में शामिल हो गए हैं जहां u.id =?

यह ठीक काम करता है, इसलिए मैंने सोचा कि यह उसकी कारों के साथ और उसके दोस्तों को निम्न क्वेरी के साथ साथ एक उपयोगकर्ता प्राप्त करने के लिए आसान होगा: उपयोगकर्ता से
यू u.cars लाने में शामिल होने के लिए छोड़ दिया शामिल होने u.friends जहां लाने के लिए छोड़ दिया u.id =?

लेकिन यह मुझे निम्न त्रुटि देता है:
HibernateException: एक साथ कई बैग

अब नहीं लाई जा सकती है मेरी सवाल यह है: हाइबरनेट में एक से अधिक बच्चों को लाने के लिए सही तरीके से क्या है?

+0

डुप्लिकेट: http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags। हाइबरनेट उपयोग के साथ: @LazyCollection (LazyCollectionOption.FALSE) – willome

उत्तर

10

बच्चों में से एक संग्रह संग्रह में एक बैग होना चाहिए (यानी एक सूची के रूप में घोषित किया जाना चाहिए)। सेट के रूप में अन्य संग्रह घोषित करें, और यह काम करेगा।

सावधान रहें, हालांकि, इस तरह के fetch में शामिल होने से पंक्तियों का एक कार्टिसियन उत्पाद बनाता है। यदि दोनों संग्रहों में 100 तत्व हैं, तो ऐसी क्वेरी डेटाबेस के लिए 10,000 पंक्तियों को पुनर्प्राप्त करती है। कभी-कभी एक पहली क्वेरी निष्पादित करने के लिए और अधिक कुशल होता है जो एक संग्रह प्राप्त करता है, और दूसरा जो दूसरे को प्राप्त करता है (जिससे 200 तक पंक्तियों की संख्या कम हो जाती है)। यह आपके पास होने वाली समस्या से बचने का भी एक तरीका है:

select u from User u left join fetch u.cars where u.id = :id; 
select u from User u left join fetch u.friends where u.id = :id; 
+1

जानना अच्छा लगा। यह सहजता से स्पष्ट नहीं है कि स्कैंड क्वेरी वास्तव में पहली क्वेरी द्वारा लोड की गई समान उपयोगकर्ता इकाइयों पर मित्रों के संग्रह को पॉप्युलेट करेगी।लेकिन इस तरह यह काम करता है (कैश के लिए धन्यवाद)! –

+1

क्या इन दो एचएसक्यूएल प्रश्नों को एक '@ नामांकित' के अंदर लिखा जा सकता है? – MyTitle

+0

@MyTitle: नहीं। एक नामित क्वेरी एक एकल क्वेरी है, दो नहीं। –

6

आपने संग्रह/सूची (बैग) समस्या को अभी हिट किया है।

यहां इस बारे में एक हाइबरनेट आधिकारिक "मुद्दा" का एक लिंक है: https://hibernate.atlassian.net/browse/HHH-1718। जैसा कि आप देख सकते हैं, यह 2006 में खुला है और अभी भी खुला है।

जेबी निजेट का प्रस्ताव देने के अलावा, मेरा सुझाव है कि आप अपने मॉडल में संग्रह या सूची के बजाय सेट का उपयोग करें (यदि आप कर सकते हैं), अन्यथा, आप FetchMode.SUBSELECT के रूप में अपना संग्रह/सूची भी निर्दिष्ट कर सकते हैं और अंतिम विकल्प के रूप में (कार्यान्वित करने के लिए दर्दनाक), आप अपने @ OneToMany/@ ManyToMany पर @IndexColumn का उपयोग कर सकते हैं।

इस ब्लॉग लेख को लागू समाधान में आपका मार्गदर्शन करेगा: http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

दूसरे शब्दों में, वहाँ वास्तव में क्या करना है आप, क्या करने के लिए समाधान को छोड़कर चाहते हैं कोई समाधान नहीं है।

आशा है कि इससे मदद मिलती है!

संपादित करें: टाइपो

0

संभव नहीं के रूप में यह आवेदन/डेटाबेस के लिए बहुत भारी हो सकता है, आप अलग से 2 अलग मापदंड डेटा बना सकते हैं और पुनः प्राप्त करने की जरूरत है।

Cat cat = sess.createCriteria(Cat.class) 
       .add(Restrictions.like("name", "F%")) 
       .uniqueResult(); 

List kitten = sess.createCriteria(Kitten.class) 
        .add(Restrictions.eq("cat", cat)) 
        .createCriteria("kittens") 
        .add(Restrictions.like("name", "F%")) 
        .list(); 

List mate = sess.createCriteria(Mate.class) 
       .add(Restrictions.eq("cat", cat)) 
       .createCriteria("mate") 
       .add(Restrictions.like("name", "F%")) 
       .list(); 
संबंधित मुद्दे