2011-04-28 13 views
34

निम्नलिखित जेपीक्यूएल क्वेरी पर विचार करें:JPA 2 CriteriaQuery के रूप में "कहां" खंड के साथ जेपीक्यूएल "fetch में शामिल हों" को सही ढंग से कैसे व्यक्त करें?

SELECT foo FROM Foo foo 
INNER JOIN FETCH foo.bar bar 
WHERE bar.baz = :baz 

मैं इसे क्रिटिएरिया क्वेरी में अनुवाद करने की कोशिश कर रहा हूं। यह जहां तक ​​मैंने प्राप्त किया है:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class); 
Root<Foo> r = cq.from(Foo.class); 
Fetch<Foo, Bar> fetch = r.fetch(Foo_.bar, JoinType.INNER); 
Join<Foo, Bar> join = r.join(Foo_.bar, JoinType.INNER); 
cq.where(cb.equal(join.get(Bar_.baz), value); 

यहां स्पष्ट समस्या यह है कि मैं वही दो बार जुड़ रहा हूं, क्योंकि Fetch<Foo, Bar> में Path प्राप्त करने की कोई विधि नहीं है। क्या दो बार जुड़ने से बचने का कोई तरीका है? या क्या मुझे एक पुराने प्रश्न के साथ अच्छे पुराने जेपीक्यूएल के साथ रहना होगा?

+1

अच्छा, धन्यवाद, लेकिन मैं मानक एपीआई के साथ ज्यादा चिपकना चाहता हूं और अतिरिक्त तृतीय पक्ष पुस्तकालयों से बचने की कोशिश करता हूं। यदि मैं जेपीए मानदंड एपीआई के साथ क्या करना चाहता हूं, तो शायद मैं सिर्फ सादे जेपीक्यूएल के साथ रहूंगा। – chris

+0

क्या आपने अपनी समस्या हल की है? मुझे एक ही समस्या है। लाने के लिए प्राप्त नहीं किया जा सकता है, और मुझे Fetch से पथ नहीं मिल सकता है। यह व्यावहारिक रूप से अनुपयोगी है। केवल समाधान दो समान जुड़ना है, जो स्वीकार्य नहीं है। – svlada

+0

खैर, जेम्स का जवाब इस मुद्दे की जड़ को काफी अच्छी तरह से वर्णन करता है। आप बस इसे इस तरह से नहीं कर सकते हैं, और यह एक ध्वनि डिजाइन निर्णय है। अगर मुझे सही याद है, तो मैं वास्तव में दो बार शामिल हो गया। कहा जा रहा है कि, यदि मेरे पास विकल्प है, तो मैं पहले कभी जेपीए का उपयोग नहीं करूंगा, क्योंकि मुझे लगता है कि यह एक बेकार अमूर्त परत है जो अंतर्निहित कार्यान्वयन को बढ़ावा देने के दौरान अनावश्यक जटिलता को जोड़ती है। – chris

उत्तर

52

जेपीक्यूएल में यह वास्तव में कल्पना में सच है। जेपीए स्पेक एक उपनाम में शामिल होने के लिए उपनाम को अनुमति नहीं देता है। मुद्दा यह है कि आप शामिल होने के संदर्भ को प्रतिबंधित करके आसानी से अपने आप को पैर में शूट कर सकते हैं। दो बार जुड़ना सुरक्षित है।

यह आमतौर पर ToOnes से ToMany के साथ एक मुद्दा है। उदाहरण के लिए,

Select e from Employee e 
join fetch e.phones p 
where p.areaCode = '613' 

यह होगा गलत तरीके से वापसी सभी कर्मचारी है कि '613' क्षेत्र कोड में संख्याएँ शामिल लेकिन उसके परिणाम सूची में अन्य क्षेत्रों के फोन नंबर बाहर छोड़ दिया जाएगा। इसका मतलब है कि जिस कर्मचारी के पास 613 और 416 क्षेत्र कोड में फोन था, वह 416 फोन नंबर खो देगा, इसलिए ऑब्जेक्ट दूषित हो जाएगा।

अनुमोदित, यदि आप जानते हैं कि आप क्या कर रहे हैं, तो अतिरिक्त जुड़ाव वांछनीय नहीं है, कुछ जेपीए प्रदाता शामिल होने से एलियासिंग को अनुमति दे सकते हैं, और मानदंड को शामिल करने के लिए प्राप्त करने की अनुमति दे सकते हैं।

+2

शानदार जवाब, धन्यवाद। उस बारे में सोचा नहीं था। हाइबरनेट ने कभी भी मुझे शामिल होने के बारे में शिकायत नहीं की, मुझे पता नहीं था कि यह वास्तव में spec का उल्लंघन करता है। – chris

+4

यह भी देखें, http://java-persistence-performance.blogspot.com/2012/04/objects-vs-data-and-filtering-join.html – James