2010-09-10 16 views
26

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

एसक्यूएल 99 मानक कीवर्ड "नलस लॉस्ट" प्रदान करता है यह घोषणा करने के लिए कि शून्य मानों को नल की तुलना में कम रखा जाना चाहिए।

हाइबरनेट के मानदंड API का उपयोग करके "अंतिम अंतिम" व्यवहार प्राप्त किया जा सकता है?

उत्तर

14

यह देखते हुए कि HHH-465 तय नहीं है और सुभाष Ebersole द्वारा दिए गए कारण के लिए एक निकट भविष्य में तय करने के लिए नहीं जा रहा है, आपका सबसे अच्छा विकल्प CustomNullsFirstInterceptor या तो विश्व स्तर पर इस मुद्दे को से जुड़ी उपयोग करने के लिए किया जाएगा या विशेष रूप से एसक्यूएल कथन को बदलने के लिए।

public class CustomNullsFirstInterceptor extends EmptyInterceptor { 

    private static final long serialVersionUID = -3156853534261313031L; 

    private static final String ORDER_BY_TOKEN = "order by"; 

    public String onPrepareStatement(String sql) { 

     int orderByStart = sql.toLowerCase().indexOf(ORDER_BY_TOKEN); 
     if (orderByStart == -1) { 
      return super.onPrepareStatement(sql); 
     } 
     orderByStart += ORDER_BY_TOKEN.length() + 1; 
     int orderByEnd = sql.indexOf(")", orderByStart); 
     if (orderByEnd == -1) { 
      orderByEnd = sql.indexOf(" UNION ", orderByStart); 
      if (orderByEnd == -1) { 
       orderByEnd = sql.length(); 
      } 
     } 
     String orderByContent = sql.substring(orderByStart, orderByEnd); 
     String[] orderByNames = orderByContent.split("\\,"); 
     for (int i=0; i<orderByNames.length; i++) { 
      if (orderByNames[i].trim().length() > 0) { 
       if (orderByNames[i].trim().toLowerCase().endsWith("desc")) { 
        orderByNames[i] += " NULLS LAST"; 
       } else { 
        orderByNames[i] += " NULLS FIRST"; 
       } 
      } 
     } 
     orderByContent = StringUtils.join(orderByNames, ","); 
     sql = sql.substring(0, orderByStart) + orderByContent + sql.substring(orderByEnd); 
     return super.onPrepareStatement(sql); 
    } 

} 
+3

सुंदर समाधान, मैंने इंटरसेप्टर के बारे में सोचा नहीं है, धन्यवाद! यदि कोई और इसका उपयोग करना चाहता है, तो आपको इस लाइन को अपनी persistence.xml फ़ाइल में जोड़ना होगा: mgamer

+0

यह ब्रेक होता है यदि एसक्यूएल – Sathish

+2

वाह द्वारा ऑर्डर के बाद सीमा/ऑफसेट है, कि हाइबरनेट जेआईआरए ** 2005 ** – atrain

0
+0

मैंने आखिरी हाइबरनेट संस्करण डाउनलोड किया है और व्यवहार में कोई बदलाव नहीं देखा है। क्या तुम? इसके अलावा, टिकट की औपचारिक स्थिति अभी भी खोली गई है और अनसुलझा है। – mgamer

2

यहाँ से (पास्कल Thivent) वर्ग के लिए मेरी अद्यतन है::

मैं इसे नीचे पाठकों (एमिलियो डोल्से के लिए क्रेडिट) के लिए पोस्टिंग कर रहा हूँ

for (int i = 0; i < orderByNames.length; i++) { 
    if (orderByNames[i].trim().length() > 0) { 
     String orderName = orderByNames[i].trim().toLowerCase(); 
     if (orderName.contains("desc")) { 
      orderByNames[i] = orderName.replace("desc", "desc NULLS LAST"); 
     } else { 
      orderByNames[i] = orderName.replace("asc", "asc NULLS FIRST"); 
     } 
    } 
} 

इस समस्या का समाधान होता :

यह टूट जाता है, तो एसक्यूएल है सीमा/द्वारा आदेश के बाद ऑफसेट - सतीश अप्रैल 1 '11 14:52

पर

भी इस तरीके से जेपीए (हाइबरनेट) के भीतर इस का उपयोग कर सकते हैं:

Session session = entityManager.unwrap(Session.class); 
Session nullsSortingProperlySession = null; 
try { 
    // perform a query guaranteeing that nulls will sort last 
    nullsSortingProperlySession = session.getSessionFactory().withOptions() 
     .interceptor(new GuaranteeNullsFirstInterceptor()) 
     .openSession(); 
} finally { 
    // release the session, or the db connections will spiral 
    try { 
     if (nullsSortingProperlySession != null) { 
      nullsSortingProperlySession.close(); 
     } 
    } catch (Exception e) { 
     logger.error("Error closing session", e); 
    } 
} 

मैं postgres पर इस परीक्षण किया है और यह ठीक करता है मुद्दा यह है कि हम कर रहे थे 'nulls गैर nulls तुलना में अधिक है' ।

2

एक और प्रकार, यदि आप मक्खी पर एसक्यूएल बना सकते हैं और मानदंड एपीआई का उपयोग नहीं करते: COALESCE (, '0') द्वारा

आदेश [एएससी | DESC]

यह या तो varchar के लिए या काम करता है संख्यात्मक कॉलम।

+0

के साथ तय किया गया था क्या आप निश्चित हैं , COALESCE को हाइबरनेट द्वारा समर्थित किया गया है? मूल एसक्यूएल में एबेन, मुझे यकीन नहीं है कि सभी डीएमएस इसका समर्थन करते हैं? –

+0

मैंने इसे PostgreSQL और Oracle के साथ परीक्षण किया है। और, कोलेसे Ansi SQL-92 मानक का हिस्सा है, इसलिए यह होना चाहिए सभी विक्रेताओं द्वारा समर्थित। –

34

यह सुविधा पहले उल्लेखित हाइबरनेट 4.2.x और 4.3.x रिलीज़ के दौरान लागू की गई है।

यह उदाहरण के लिए के रूप में इस्तेमाल किया जा सकता:

Criteria criteria = ...; 
criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST)); 

हाइबरनेट v4.3 javadocs कम चूक से भरी here हैं।

+1

यह नया सही उत्तर है। – MarcG

+0

बहुत खुशी है कि मैं नीचे स्क्रॉल करता हूं। यह हर बार होता जा रहा है। सर्वश्रेष्ठ उत्तर स्वीकार्य उत्तर नहीं है। –

2

हाइबरनेट गुणों में आप "नल्स फर्स्ट"/"नल्स आखिरी" कॉन्फ़िगर कर सकते हैं, इसलिए इसे डिफ़ॉल्ट रूप से किसी भी मानदंड कॉल द्वारा उठाया जाएगा: hibernate.order_by.default_null_ordering=last (या =first)।

विवरण के लिए this hibernate commit देखें।

+0

इस समाधान के लिए धन्यवाद, हमारे मामले में, दूसरे की तुलना में क्लीनर था समाधान; कोड कोड परिवर्तन किए बिना हर समय व्यवहार करेगा। –

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