2010-02-17 11 views
16

मुझे जेपीए में नामांकित क्वेरीज़ का विचार स्थिर प्रश्नों के लिए पसंद है, लेकिन मैं अक्सर पूछताछ के साथ-साथ क्वेरी के कुछ सबसेट से परिणाम सूची के लिए गिनती परिणाम प्राप्त करना चाहता हूं। मैं दो लगभग समान नामांकित क्वेरीज़ नहीं लिखूंगा।क्या परिणाम सेट के साथ जेपीए नामांकित क्वेरी के लिए गणना आकार प्राप्त करने का कोई तरीका है?

@NamedQuery(name = "getAccounts", query = "SELECT a FROM Account") 
. 
. 
    Query q = em.createNamedQuery("getAccounts"); 
    List r = q.setFirstResult(s).setMaxResults(m).getResultList(); 
    int count = q.getCount(); 

तो मान लीजिए कि मीटर 10 है, रों 0 और वहाँ खाते में 400 पंक्तियों हैं: आदर्श रूप में, मैं क्या करना चाहते हैं की तरह कुछ है। मैं उम्मीद करता हूं कि इसमें 10 वस्तुओं की सूची होगी, लेकिन मैं जानना चाहता हूं कि कुल 400 पंक्तियां हैं। मैं एक दूसरे @NamedQuery लिख सकते हैं:

@NamedQuery(name = "getAccountCount", query = "SELECT COUNT(a) FROM Account") 

लेकिन यह एक सूखी उल्लंघन है कि अगर मैं हमेशा से ही गिनती चाहते करने जा रहा हूँ करने के लिए लगता है। इस साधारण मामले में दोनों को सिंक में रखना आसान है, लेकिन अगर क्वेरी बदलती है, तो यह आदर्श से कम लगता है कि मुझे मूल्यों को लाइन में रखने के लिए @NamedQueries दोनों को अपडेट करना होगा।

यहां एक सामान्य उपयोग केस आइटम के कुछ सबसेट लाएगा, लेकिन कुल गणना ("400 के 1-10 प्रदर्शित करना") को इंगित करने के कुछ तरीके की आवश्यकता है।

उत्तर

13

तो मैं जिस समाधान का उपयोग कर रहा हूं वह दो @NamedQuerys, परिणाम सेट के लिए एक और गिनती के लिए एक था, लेकिन डीआरवाई को बनाए रखने के लिए एक स्थिर स्ट्रिंग में आधार क्वेरी को कैप्चर करना और यह सुनिश्चित करना कि दोनों प्रश्न सुसंगत बने रहें। तो ऊपर के लिए, मैं की तरह कुछ होगा:

@NamedQuery(name = "getAccounts", query = "SELECT a" + accountQuery) 
@NamedQuery(name = "getAccounts.count", query = "SELECT COUNT(a)" + accountQuery) 
. 
static final String accountQuery = " FROM Account"; 
. 
    Query q = em.createNamedQuery("getAccounts"); 
    List r = q.setFirstResult(s).setMaxResults(m).getResultList(); 
    int count = ((Long)em.createNamedQuery("getAccounts.count").getSingleResult()).intValue(); 

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

दो प्रश्नों के बीच लगातार नामकरण करके, कोड के बॉडी को केवल क्वेरी के मूल नाम के आधार पर दोनों सेट चलाने के लिए लपेटना संभव है।

+0

अंत में नाम QUERY के लिए भी काम कर रहा है! धन्यवाद – Zavael

+0

दिलचस्प, मुझे यह भी पता नहीं था कि एनोटेशन को कॉन्फ़िगर करते समय आप स्थिर फाइनल का संदर्भ दे सकते हैं। हालांकि, मुझे लगता है कि एक समाधान जिसे दो अलग-अलग नामित प्रश्नों की आवश्यकता नहीं है, अभी भी आदर्श होगा। – aroth

5

का उपयोग setFirstResult/setMaxResults कर नहीं एक परिणाम के सेट का एक सबसेट लौटने के लिए, क्वेरी भी जब आप इन तरीकों फोन चलाने नहीं किया गया है, वे उत्पन्न चयन करें क्वेरी है कि जब getResultList बुला निष्पादित किया जाएगा प्रभावित करते हैं। यदि आप कुल रिकॉर्ड्स गिनती प्राप्त करना चाहते हैं, तो आपको अपनी इकाइयों को एक अलग क्वेरी (आमतौर पर पेजिनेट करने से पहले) में SELECT COUNT करना होगा।

एक पूर्ण उदाहरण के लिए, Pagination of Data Sets in a Sample Application using JSF, Catalog Facade Stateless Session, and Java Persistence APIs देखें।

+0

हां। मैं पूरी गिनती प्राप्त करना चाहता हूं कि क्वेरी का नतीजा होगा। इसलिए उदाहरण में गिनती r.size() से मेल नहीं खाती है या मैं बस इसका उपयोग करूंगा। एक संभावित उपयोग मामला यह है कि मैं खातों को सूचीबद्ध करने के लिए परिणामों का एक पृष्ठ प्राप्त करना चाहता हूं, लेकिन उन्हें कुल कितने पेज देने की अनुमति देने के लिए, मैं क्वेरी से कुल गिनती चाहता हूं, भले ही मैं केवल 25 परिणामों को पुनर्प्राप्त कर रहा हूं। – Tim

+0

@ टिम मैंने अपना जवाब स्पष्ट कर दिया है। यदि यह अभी भी स्पष्ट नहीं है, तो मुझे बताएं। –

+0

धन्यवाद। मैंने अपने प्रश्न को स्पष्ट करने की कोशिश की है। असल में, मुझे पता है कि संशोधक क्वेरी चलाने से पहले क्वेरी बदलते हैं। मैं जो करने की उम्मीद कर रहा हूं, उसके पास एक एकल @NamedQuery है जो सबसेट को वापस करने के साथ-साथ गिनती के लिए आधार के रूप में कार्य करता है, गिनती के लिए एक प्रश्न लिखने और रिटर्न सेट के लिए एक लिखने के बजाय। आदर्श रूप से अभी भी @NamedQuery का उपयोग कर रहे हैं। मैं आपके द्वारा संदर्भित लिंक की जांच करूंगा। – Tim

1

ओह अच्छी तरह से आप की तरह नामित प्रश्नों एनोटेशन प्राप्त करने के लिए आत्मनिरीक्षण का उपयोग कर सकते हैं:

String getNamedQueryCode(Class<? extends Object> clazz, String namedQueryKey) { 
    NamedQueries namedQueriesAnnotation = clazz.getAnnotation(NamedQueries.class); 
    NamedQuery[] namedQueryAnnotations = namedQueriesAnnotation.value(); 

    String code = null; 
    for (NamedQuery namedQuery : namedQueryAnnotations) { 
     if (namedQuery.name().equals(namedQueryKey)) { 
      code = namedQuery.query(); 
      break; 
     } 
    } 

    if (code == null) { 
     if (clazz.getSuperclass().getAnnotation(MappedSuperclass.class) != null) { 
      code = getNamedQueryCode(clazz.getSuperclass(), namedQueryKey); 
     } 
    } 

    //if not found 
    return code; 
} 
+0

यह सुनिश्चित नहीं है कि यह मेरे प्रश्न पर कैसे लागू होता है। मैं precompilation, कैशिंग और अन्य अनुकूलन के फायदे के लिए NamedQuery का उपयोग करना चाहता हूँ। मैं चाहता हूं कि दो प्रश्न एक समान परिणाम और एक गिनती लौटने के अलावा समान हों। और मैं डीआरवाई का पालन करना चाहता हूं और सशर्त खंड की प्रतिलिपि बनाना और पेस्ट नहीं करना चाहता हूं। – Tim

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

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