2012-06-14 28 views
8

मेरे पास निम्नलिखित संस्थाएं हैं; मैं लोड हो रहा हूँ टिकट और गुण प्राप्त करने में कठिनाईमानदंड एपीआई: एक सूची प्राप्त करें मुख्य इकाई दोहराई जाती है

@Entity 
public class Ticket { 

    ... 

    @OneToMany(mappedBy="ticket", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    private List<WorkOrder> workOrders = null; 

    ... 
} 

@Entity 
public class WorkOrder { 
    ... 
    @ManyToOne 
    @JoinColumn(nullable = false) 
    private Ticket ticket; 
} 

: टिकट 0, एन WorkOrder का एक सेट होता। सभी 0,1 विशेषताओं में कोई समस्या नहीं है। वर्कऑर्डर के लिए, मैंने निम्नलिखित कोड प्राप्त करने के लिए this answer का उपयोग किया।

CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); 
CriteriaQuery<Ticket> criteriaQuery = criteriaBuilder 
    .createQuery(Ticket.class); 
Root<Ticket> rootTicket = criteriaQuery.from(Ticket.class); 

ListAttribute<? super Ticket, WorkOrder> workOrders = 
    rootTicket.getModel().getList("workOrders", WorkOrder.class); 
rootTicket.fetch(workOrders, JoinType.LEFT); 

    // WHERE logic 
    ... 

criteriaQuery.select(rootTicket); 
TypedQuery<Ticket> query = this.entityManager.createQuery(criteriaQuery); 
return query.getResultList(); 

नतीजा यह है कि, एक प्रश्न है कि मुझे 5 workOrders साथ 1 टिकट लौटना चाहिए में, मैं एक ही टिकट पुन: प्राप्त करने हूँ 5 बार है।

यदि मैं सिर्फ काम करता हूं तो एक उत्सुक प्राप्त करता है और fetch कोड हटा देता है, यह काम करता है जैसा कि यह करना चाहिए।

क्या कोई मेरी मदद कर सकता है? अग्रिम में धन्यवाद।

अद्यतन:

एक के बारे में कारण है कि मैं जेबी Nizet के जवाब के साथ बस खुश नहीं हूँ स्पष्टीकरण (भले ही अंत में यह काम करता है)।

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

इस कारण के लिए कुछ उचित स्पष्टीकरण है कि जेपीए दोनों मामलों में एक ही डेटा नहीं लौटाता है?

इनाम के लिए

अद्यतन: जेबी Nizet का जवाब इस मुद्दे को हल था, मैं अभी भी यह व्यर्थ करती है, एक ही अर्थ ("Ticket जाओ और सभी WorkOrderticket.workOrders अंदर लाने") के साथ दो आपरेशन को देखते हुए एक उत्सुक लोड हो रहा है द्वारा उन्हें कर रही है fetch निर्दिष्ट करते समय कोई और परिवर्तन की आवश्यकता नहीं है DISTINCT कमांड

+0

का उपयोग कर आप को देखो, तो द्वारा एन 1 समस्या [वाम जुड़ें] (http://www.w3schools.com/sql/sql_join_left.asp), यह जिस तरह से यह काम करता है। बाएंजोइन द्वारा आपको परिणाम लाने की आवश्यकता क्यों है? – JMelnik

+0

मानदंड एपीआई में उपलब्ध तीन विकल्पों में से, यह अधिक समझदार है। हम यहां जेपीए के बारे में बात कर रहे हैं, इसलिए मुझे उम्मीद थी कि एपीआई एसक्यूएल को इकाइयों में एक और उचित तरीके से व्यवस्थित करेगी। – SJuan76

+0

मेरा संपादित उत्तर देखें। –

उत्तर

20
  1. उत्सुक लोडिंग और शामिल होने के बीच एक अंतर है। उत्सुक लोडिंग का मतलब यह नहीं है कि डेटा एक ही क्वेरी में लोड किया गया है। इसका मतलब यह है कि यह तुरंत लोड हो जाता है, हालांकि अतिरिक्त प्रश्नों से।

  2. मानदंडों का हमेशा एक SQL क्वेरी में अनुवाद किया जाता है। यदि आप जुड़ते हैं, तो यह SQL में शामिल होगा। एसक्यूएल की प्रकृति से, यह मूल इकाई के डेटा को भी गुणा करता है, जो आपके द्वारा प्राप्त प्रभाव को जन्म देता है। (ध्यान दें कि आप एक ही उदाहरण कई बार मिलता है, तो जड़ इकाई स्मृति में गुणा नहीं है।)

कि करने के लिए कई समाधान कर रहे हैं:

  • उपयोग distinct(true)
  • उपयोग अलग रूट इकाई ट्रांसफार्मर (.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY))।
  • जब आप बच्चे के गुण के आधार पर फ़िल्टर की जरूरत नहीं है,
  • में शामिल होने जब आप एक सबक्वेरी (DetachedCriteria) द्वारा बच्चे के गुण, फिल्टर के आधार पर फ़िल्टर करने की आवश्यकता से बचें।
  • अनुकूलन batch-size
4

क्या आपने CriteriaQuery पर distinct(true) पर कॉल करने का प्रयास किया है?

जेपीए 2 विनिर्देश, पेज 161, कहते हैं:

DISTINCT कीवर्ड का उल्लेख करने कि डुप्लिकेट मानों क्वेरी परिणाम से समाप्त किया जाना चाहिए किया जाता है।

यदि DISTINCT निर्दिष्ट नहीं है, तो डुप्लिकेट मान समाप्त नहीं होते हैं।

जावाडोक भी कहते हैं:

निर्दिष्ट करें कि डुप्लिकेट क्वेरी परिणाम हो जाएगा eliminated.A सच मूल्य का कारण होगा डुप्लिकेट समाप्त किया जा करने के लिए। एक झूठा मान बनाए रखने के लिए डुप्लीकेट का कारण बन जाएगा। यदि विशिष्ट निर्दिष्ट नहीं किया गया है, डुप्लिकेट परिणाम बनाए रखा जाना चाहिए।

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

+0

ठीक है, 'विशिष्ट (सत्य)' के साथ यह काम करता है। लेकिन क्या यह "सही" समाधान है या सिर्फ एक कामकाज है? मुझे लगता है कि मैं जेपीए को बता रहा हूं कि मैं सिर्फ 'टिकट' की तलाश में हूं और वर्कऑर्डरर्स को सूची में लोड किया जाना चाहिए, और जेपीए मुझे केवल कार्टेशियन उत्पाद देता है। – SJuan76

+0

मुझे लगता है कि यह सही समाधान है, क्योंकि यह अलग-अलग कीवर्ड जेपीक्यूएल (या कम से कम, एचक्यूएल में) में भी करता है। –

+1

विचलित (सत्य) के साथ केवल समस्या यह है कि यह आपके ऑर्डरबी के साथ गड़बड़ कर देता है अगर वे किसी विशेषता के गुण पर आधारित होते हैं। – TheBakker