2013-04-13 5 views
13

मैं एक प्रश्न पूछना चाहता हूं जहां मैं 2 टेबल में शामिल हो, CriteriaBuilder का उपयोग कर। MySQL में क्वेरी मैं इस प्रकार दिखाई देगा बनाने के लिए कोशिश कर रहा हूँ:एक मानदंड बिल्डर को कस्टम "चालू" स्थिति में कैसे शामिल किया जाए?

SELECT * FROM order 
LEFT JOIN item 
ON order.id = item.order_id 
AND item.type_id = 1 

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

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Order> cq = cb.createQuery(Order.class); 
Root<Order> order = cq.from(Order.class); 
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT); 
Join<Item, Type> type = order.join(Item_.type, JoinType.LEFT); 
cq.select(order); 
cq.where(cb.equal(type.get(Type_.id), 1)); 

इस क्वेरी को तोड़ दिया है, क्योंकि यह MySQL में कुछ इस तरह का परिणाम:

SELECT * FROM order 
LEFT JOIN item 
ON order.id = item.order_id 
WHERE item.type_id = 1 

परिणाम केवल # 1 प्रकार की वस्तुओं के साथ आदेश शामिल होंगे। बिना आदेश दिए गए आदेश। पहले उदाहरण में क्वेरी बनाने के लिए मैं मानदंडबिल्डर का उपयोग कैसे कर सकता हूं?

+0

_ मैं सभी ऑर्डर प्राप्त करना चाहता हूं और यदि उनके पास प्रकार # 1 का कोई आइटम है, तो इस आइटम को परिणाम में शामिल किया जाना चाहिए_ आप किस परिणाम प्रकार चाहते हैं? आदेश? या एक tuple/multiselect? आप सभी आदेशों की तुलना में _more_ क्या चाहते हैं? कृपया – perissf

+0

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

+0

मानदंडबिल्डर के साथ यह संभव है! मेरे उत्तर को देखें – Mitchapp

उत्तर

1

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

JPA Criteria API: Multiple condition on LEFT JOIN

+0

पहला MySQL वह है जो मैं अपने मानदंडबिल्डर को उत्पन्न करना चाहता हूं। दूसरा MySQL दर्शाता है कि दिखाया गया CriteriaQuery क्या उत्पन्न करता है। यदि मैं बस दूसरी MySQL क्वेरी में 'या item.id शून्य' जोड़ता हूं, तो मुझे वह नहीं मिल रहा है जो मैं चाहता हूं। ऐसा करने से उन वस्तुओं के साथ ऑर्डर बहिष्कृत किए जाएंगे जिनके पास टाइप 1 से भिन्न प्रकार है, और केवल टाइप 1 या आइटम के आइटम के साथ ऑर्डर लौटाएं। –

+0

मुझे अब यह Bjørn मिलता है। मैं अपना जवाब संपादित कर रहा हूं। – carbontax

+0

धन्यवाद। मैं इसे एक छोटे पैमाने पर आज़मा सकता हूं, लेकिन मेरी वर्तमान परियोजना पर शायद यह मेरी मदद नहीं करेगा। अभी मैं एक्लिप्ससेंक (जेपीए 2.0) पर हूं। जहां तक ​​मैं पता लगाने में सक्षम हूं ([link] (https://blogs.oracle.com/arungupta/entry/jpa_2_1_early_draft)), मुझे जो सुविधा चाहिए वह जेपीए 2.1 तक उपलब्ध नहीं होगी। उम्मीद है कि यह जल्द ही होगा। –

0

मैं जानता हूँ कि इस सवाल का एक लंबे समय के एक जाना बनाया गया था, लेकिन हाल ही में एक ही समस्या थी और मैं एक Oracle मंच से इस समाधान मिल गया, मैं कॉपी और पेस्ट की सिर्फ मामले में लिंक अब नहीं है उपलब्ध।

MiguelChillitupaArmijos 29 ABR-2011 01:41 (एन respuesta एक 840,578) में सोचो आप की तरह कुछ का उपयोग करना चाहिए:

em.createQuery("SELECT DISTINCT e.Id" + 
        " from Email e " + 
        " left join e.idEmailIn e2 *with* e2.responseType = 'response'" + 
        "  where e.type = 'in' and e.responseMandatory = true").getSingleResult(); 

एक इस कड़ी है।

JPA Criteria : LEFT JOIN with an AND condition

-1

वहाँ एक समाधान है, अगर आप जेपीए 2.0 यह बेहतर समाधान नहीं है के साथ हाइबरनेट 3.6 का उपयोग कर रहे है, लेकिन यह मेरे लिए एकदम सही काम करता है।

मैंने @Where हाइबरनेट एनोटेशन के साथ इकाई को डुप्लिकेट किया है। इसका मतलब है कि हर बार जब आप इस इकाई के साथ जुड़ने का उपयोग करते हैं, तो हाइबरनेट जेनरेट किए गए SQL पर शामिल कथन पर अतिरिक्त स्थिति जोड़ देगा।

उदाहरण के लिए, शुरू में हम पालन उदाहरण है:

@Entity 
@Table(name = "PERSON") 
public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private Long id; 

    @Id 
    @Column(name = "PERSON_NAME") 
    private String name; 

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY) 
    private Set<Address> addresses; 

} 

@Entity 
@Table(name = "ADDRESS") 
public class Address { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private Long id; 

    @Id 
    @Column(name = "ADDRESS_STREET") 
    private String street; 

    @ManyToOne 
    @JoinColumn(name = "PERSON_ID") 
    private Person person; 

} 

अतिरिक्त शर्तों को जोड़ने के लिए मापदंड शामिल हों पर, हम पता @Entity मानचित्रण नकल की जरूरत है, @Where एनोटेशन @Where जोड़ने के क्रम (खंड में = "ADDRESS_TYPE_ID = 2")।

@Entity 
@Table(name = "ADDRESS") 
@Where(clause = " ADDRESS_TYPE_ID = 2") 
public class ShippingAddress { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private Long id; 

    @Id 
    @Column(name = "ADDRESS_STREET") 
    private String street; 

    @OneToOne 
    @JoinColumn(name = "PERSON_ID") 
    private Person person; 

} 

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

PersonRoot.join(Person_.shippingAddress, JoinType.LEFT); 

हाइबरनेट स्निपेट एसक्यूएल चाहिए इस तरह लगता है:

left outer join 
     address shippingadd13_ 
      on person11_.person_id=shippingadd13_.person_id 
      and (
       shippingadd13_.ADDRESS_TYPE_ID = 2 
      ) 
4

आप क्या कर सकते

@Entity 
@Table(name = "PERSON") 
public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private Long id; 

    @Id 
    @Column(name = "PERSON_NAME") 
    private String name; 

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY) 
    private Set<Address> addresses; 

    @OneToOne(mappedBy = "person") 
    private ShippingAddress shippingAddress; 

} 

अंत में, आप एक अपने मानदंडों में इस विशिष्ट इकाई के साथ शामिल होने के लिए उपयोग कर सकते कि on विधि Join<Z, X> on(Predicate... restrictions); का उपयोग कर।

यहाँ एक काम कर उदाहरण है:

... 
Root<Order> order = cq.from(Order.class); 
Join<Order, Item> item = order.join(Order_.itemList, JoinType.LEFT); 
item.on(cb.equal(item.get(Item_.type), 1)); 
... 
+0

के अंतर्गत देखें यदि यह काम करता है तो कुछ मूल प्रश्न होंगे जिन्हें प्रतिस्थापित किया जा सकता है। अगली बार जब मुझे जॉइन-ऑन की ज़रूरत है तो मैं इसे आजमाएं। –

+0

मुझे "कुछ मूल प्रश्नों को प्रतिस्थापित किया जा सकता है" से आपका क्या मतलब नहीं मिला! इसे पहले आज़माएं और आप देखेंगे कि यह पूरी तरह से काम करता है! – Mitchapp

+0

मेरा मतलब था कि मेरे पास बहुत सारे स्थान हैं जहां मैं 'entityManager.createNativeQuery (स्ट्रिंग) का उपयोग करता हूं क्योंकि मानदंडबिल्डर की कमियों की वजह से। :-) –

0

खंड पर हाइबरनेट में समर्थित है 4.3 संस्करण, किसी को भी जानकारी है, अगर वहाँ के सूचकांक के साथ अतिरिक्त कस्टम स्थिति का पैरामीटर सूचकांक के बीच एक पैरामीटर अनुक्रमण मुद्दा है मौजूदा क्लैपिंग पर मौजूदा मैपिंग फ़िल्टर करते समय मौजूदा मैपिंग फ़िल्टर?

उदाहरण के रूप में नीचे व्यक्ति इकाई वर्ग का उपयोग करके, कहें कि मैं इस प्रकार को फ़िल्टर प्रकारों को सीमित करने के लिए जोड़ रहा हूं और फ़िल्टर इन खंड को पॉप्युलेट करने के लिए सक्षम है। आईएन क्लॉज के लिए पैरामीटर इंडेक्स समस्या [2] का कारण बनता है जब मैं ऑन क्लॉज के अतिरिक्त शर्तों को जोड़ता हूं (जैसे 'स्ट्रीट' कॉलम का उपयोग करना)। क्या ज्ञात मुद्दा है?

[1] @Filter (नाम = "addressTypes", दशा = "में (ADDRESS_TYPE: supportedTypes)")

[2] की वजह से: त्रुटि 22,018: प्रकार BIGINT के लिए अमान्य वर्ण स्ट्रिंग प्रारूप। निजी सेट पते;

संबंधित मुद्दे

 संबंधित मुद्दे