2008-10-14 21 views
45

हाइबरनेट का उपयोग करके यूनियन क्वेरी को लागू करने के लिए मुझे क्या विकल्प हैं? मुझे पता है कि हाइबरनेट इस समय यूनियन प्रश्नों का समर्थन नहीं करता है, अभी एक यूनियन बनाने के लिए एकमात्र तरीका एक दृश्य तालिका का उपयोग करना है।हाइबरनेट यूनियन विकल्प

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

+2

समाधान में से एक कुल इकाई का उपयोग करना है, (http://stackoverflow.com/questions/ 7322526/हाइबरनेट-जेपीए-है यह संभव करने के लिए पुनः प्राप्त-विषम-संस्थाओं में एक-एकल कुए/7322738 # 7322738)। –

उत्तर

22

दृश्य का उपयोग करें। इकाई वर्ग का उपयोग कर एक ही कक्षा को अलग-अलग तालिकाओं/दृश्यों में मैप किया जा सकता है, इसलिए आपके पास बहुत अधिक डुप्लिकेशन नहीं होगा। वहां होने के नाते, ऐसा किया, ठीक काम करता है।

सादा जेडीबीसी की एक और छिपी समस्या है: यह हाइबरनेट सत्र कैश से अनजान है, इसलिए लेनदेन के अंत तक कुछ कैश किया गया है और हाइबरनेट सत्र से नहीं फंस गया है, जेडीबीसी क्वेरी इसे नहीं मिलेगी। कभी-कभी बहुत परेशान हो सकता है।

+2

और यहां तक ​​कि और अधिक परेशानी होती है जब आपके पास दूसरी-स्तर की कैश होती है, लेकिन एप्लिकेशन के किसी अन्य भाग से सादा जेडीबीसी (रिपोर्टिंग के लिए कहें) का उपयोग करें। – javashlook

5

मुझे व्लादिमीर से सहमत होना है। मैंने भी एचक्यूएल में यूनियन का उपयोग करने में देखा और इसके चारों ओर एक रास्ता नहीं मिला। अजीब चीज यह थी कि मुझे (हाइबरनेट एफएक्यू में) मिल सकता है कि यूनियन असमर्थित है, यूनियन को 'फिक्स्ड' चिह्नित लोगों से संबंधित बग रिपोर्ट, लोगों के समाचार समूह कह रहे हैं कि कथन यूनियन में कटौती की जाएगी, और अन्य समाचार समूह इसे रिपोर्ट करने वाले लोगों के समाचार समूह ठीक है ... इसके साथ मिलन करने के एक दिन बाद, मैंने अपने एचक्यूएल को सादे एसक्यूएल पर वापस बंद कर दिया, लेकिन डेटाबेस में एक दृश्य में ऐसा करना एक अच्छा विकल्प होगा। मेरे मामले में, क्वेरी के कुछ हिस्सों को गतिशील रूप से जेनरेट किया गया था, इसलिए मुझे इसके बजाय कोड में एसक्यूएल बनाना पड़ा।

+1

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

3

एक दृश्य एक बेहतर दृष्टिकोण है लेकिन चूंकि एचक्यूएल आमतौर पर एक सूची या सेट देता है ... आप list_1 कर सकते हैं .addAll (list_2)। पूरी तरह से एक संघ की तुलना में बेकार है लेकिन काम करना चाहिए।

0

मैं भी इस दर्द से गुजर रहा हूं - यदि क्वेरी गतिशील रूप से जेनरेट की गई है (उदा। हाइबरनेट मानदंड) तो मुझे इसे करने का व्यावहारिक तरीका नहीं मिला।

मेरे लिए अच्छी खबर यह थी कि मैं केवल ओरेकल डेटाबेस में 'या' का उपयोग करते समय प्रदर्शन समस्या को हल करने के लिए संघ की जांच कर रहा था।

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

2

शायद मुझे हल करने के लिए एक और सीधी-आगे समस्या थी। मेरा 'उदाहरण के लिए' जेपीए में हैबर्नेट के साथ जेपीए प्रदाता के रूप में था।

मैंने तीन चयनों (दो दूसरे मामले में दो) को कई चयनों में विभाजित किया और एकत्रित संग्रहों को संयुक्त रूप से बदल दिया, प्रभावी रूप से 'यूनियन ऑल' को बदल दिया।

+2

यह काम करता है, लेकिन यह कम खर्चीला है। –

54

आप इस्तेमाल कर सकते हैं id in (select id from ...) or id in (select id from ...)

उदा के बजाय गैर काम

from Person p where p.name="Joe" 
union 
from Person p join p.children c where c.name="Joe" 

आप कम से कम MySQL का उपयोग कर

from Person p 
    where p.id in (select p1.id from Person p1 where p1.name="Joe") 
    or p.id in (select p2.id from Person p2 join p2.children c where c.name="Joe"); 

कर सकता है, तो आप प्रदर्शन समस्याओं में इसके साथ बाद में, हालांकि चलेंगे। यह कभी कभी एक गरीब आदमी का बजाय दो प्रश्नों पर शामिल होने के ऐसा करने के लिए आसान है:

// use set for uniqueness 
Set<Person> people = new HashSet<Person>((List<Person>) query1.list()); 
people.addAll((List<Person>) query2.list()); 
return new ArrayList<Person>(people); 

यह अक्सर एक जटिल एक से दो सरल प्रश्नों करने के लिए बेहतर है।

संपादित करें:

एक उदाहरण देने के लिए, यहाँ सबसिलेक्ट समाधान से उत्पन्न MySQL क्वेरी के उत्पादन में व्याख्या है:

mysql> explain 
    select p.* from PERSON p 
    where p.id in (select p1.id from PERSON p1 where p1.name = "Joe") 
     or p.id in (select p2.id from PERSON p2 
     join CHILDREN c on p2.id = c.parent where c.name="Joe") \G 
*************************** 1. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: a 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 247554 
     Extra: Using where 
*************************** 2. row *************************** 
      id: 3 
    select_type: DEPENDENT SUBQUERY 
     table: NULL 
     type: NULL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: NULL 
     Extra: Impossible WHERE noticed after reading const tables 
*************************** 3. row *************************** 
      id: 2 
    select_type: DEPENDENT SUBQUERY 
     table: a1 
     type: unique_subquery 
possible_keys: PRIMARY,name,sortname 
      key: PRIMARY 
     key_len: 4 
      ref: func 
     rows: 1 
     Extra: Using where 
3 rows in set (0.00 sec) 

सबसे महत्वपूर्ण बात, 1. पंक्ति किसी भी सूचकांक का उपयोग नहीं करता है और 200k + पंक्तियों पर विचार करता है। खराब! इस प्रश्न के निष्पादन में 0.7 के पहिये हुए थे, दोनों सबक्वायरी मिलीसेकंड में हैं।

4

मेरे पास एचक्यूएल में यूनियन के साथ एक महत्वपूर्ण परिदृश्य (जिसके लिए मैंने बहुत संघर्ष किया) का समाधान किया है।

उदा। इसके बजाय काम नहीं कर की: -

select i , j from A a , (select i , j from B union select i , j from C) d where a.i = d.i 

या

select i , j from A a JOIN (select i , j from B union select i , j from C) d on a.i = d.i 

आप हाइबरनेट HQL में कर सकता है ->

Query q1 =session.createQuery(select i , j from A a JOIN B b on a.i = b.i) 
List l1 = q1.list(); 

Query q2 = session.createQuery(select i , j from A a JOIN C b on a.i = b.i) 
List l2 = q2.list(); 

तो यू दोनों सूची में जोड़ सकते हैं ->

l1.addAll(l2); 
+1

यूनियन प्रक्रिया में होगा, डेटाबेस द्वारा नहीं किया गया है, यह वॉल्ट के सुझाव के समान है। –

+0

तो, और यदि आप यहां सॉर्ट करना चाहते हैं तो क्या होगा? आप एक और मर्ज एल्गोरिदम लागू करके सॉर्ट तंत्र को डुप्लिकेट कर सकते हैं। बहुत अच्छा नहीं है – Bondax

0



के रूप में पैट्रिक ने कहा, प्रत्येक से जोड़कर सूची रों का चयन एक अच्छा विचार हो लेकिन याद रखें कि यह यूनिअन सभी की तरह काम करता होगा। इस दुष्प्रभाव से बचने के लिए, अगर अंतिम संग्रह में ऑब्जेक्ट पहले से जोड़ा गया है या नहीं, तो बस नियंत्रित करें। यदि नहीं, तो इसे जोड़ें। बाकी
कुछ है कि आप के बारे में ध्यान देना चाहिए अगर आपके पास है कि किसी भी शामिल हों प्रत्येक मेंचयन, परिणाम वस्तु सरणी (List<Objetc[]>) की एक सूची होगा ताकि आप करने के लिए इस पर पुनरावृति करने के लिए केवल वस्तु रख आपको इसकी ज़रूरत है।

आशा है कि यह काम करता है।

0

यहां एक विशेष मामला है, लेकिन आप अपना खुद का काम बनाने के लिए प्रेरित कर सकते हैं। यहां लक्ष्य दो अलग-अलग तालिकाओं से रिकॉर्ड्स की कुल संख्या को गिनना है जहां रिकॉर्ड एक विशेष मानदंड को पूरा करते हैं। मेरा मानना ​​है कि यह तकनीक किसी भी मामले के लिए काम करेगी जहां आपको कई तालिकाओं/स्रोतों से डेटा एकत्र करने की आवश्यकता है।

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

@Entity 
@NamedQueries({ 
     @NamedQuery(
      name ="PIXEL_ALL", 
      query = "" + 
        " SELECT new SourceCount(" + 
        "  (select count(a) from PIXEL_LOG_CURR1 a " + 
        "  where to_char(a.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " + 
        " )," + 
        "  (select count(b) from PIXEL_LOG_CURR2 b" + 
        "  where to_char(b.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " + 
        " )" + 
        ") from Dual1" + 
        "" 
    ) 
}) 

public class SourceCount { 
    @Id 
    private Long COUNT; 

    public SourceCount(Long COUNT1, Long COUNT2) { 
     this.COUNT = COUNT1+COUNT2; 
    } 

    public Long getCOUNT() { 
     return COUNT; 
    } 

    public void setCOUNT(Long COUNT) { 
     this.COUNT = COUNT; 
    } 
} 

जादू यहां का एक हिस्सा एक डमी तालिका बना सकते हैं और में एक रिकॉर्ड सम्मिलित करने के लिए है:

QueryParms parms=new QueryParms(); 
parms.put("PROCDATE",PROCDATE); 

Long pixelAll = ((SourceCount)Fetch.row("PIXEL_ALL",parms,logger)).getCOUNT(); 

आप यहाँ देख सकते हैं, नामित क्वेरी एक संघ बयान की तरह एक aweful बहुत देखने के लिए शुरू होता है यह। मेरे मामले में, मैंने इसे दोहरी 1 नाम दिया क्योंकि मेरा डेटाबेस ओरेकल है, लेकिन मुझे नहीं लगता कि यह डमी टेबल कहलाता है।

@Entity 
@Table(name="DUAL1") 
public class Dual1 { 
    @Id 
    Long ID; 
} 

अपने डमी रिकॉर्ड सम्मिलित करने को न भूलें: के रूप में [यहां] वर्णित

SQL> insert into dual1 values (1); 
संबंधित मुद्दे