2013-03-04 4 views
7

बहु-कॉलम आईडी वाले एक इकाई के लिए, हमें उन सभी वस्तुओं को किसी दिए गए सूची में जारी रखने की आवश्यकता है जो डीबी में पहले से मौजूद नहीं है। चूंकि वस्तुओं की जांच करने की संख्या बड़ी है, और भंडारण में वस्तुओं की संख्या बहुत बड़ी हो सकती है, इसलिए विचार है कि मौजूदा मल्टी-कॉलम निजी कुंजी और "जहां ... IN (। ..) "टाइप स्टेटमेंट जो मापदंड एपीआई का उपयोग करके बनाया गया है, ताकि उन्हें जारी रखने से पहले सूची से निकाल दिया जा सके।जेपीए के मानदंड एपीआई का उपयोग करके एक बहु-कॉलम "कहां ... IN" अभिव्यक्तियों का निर्माण कैसे करता है?

यहाँ कोड है कि ऐसा करने के लिए प्रयास करता है:

[EL Fine]: sql:...--SELECT SUBINDEX, ... FROM CDRS WHERE ((?, ?, ?, ?) IN ((?, ?, ?, ?), (?, ?, ?, ?), ...)) 
bind => [null, null, null, null, 2, 1362400759, 19415, 176, ...] 
:

public void persistUnique(List<CdrEntity> cdrs) { 
     // find all the CDRs in the collection that are already in the DB 
     CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); 
     CriteriaQuery<CdrEntity> query = criteriaBuilder.createQuery(CdrEntity.class); 
     Root<CdrEntity> cdrRoot = query.from(CdrEntity.class); 
     query.select(cdrRoot).where(cdrRoot.in(cdrs)); 
     List<CdrEntity> nonUnique = entityManager.createQuery(query).getResultList(); 
     // remove nonUnique elements from crds and persist 
     ... 
    } 

हालांकि, कम से कम EclipseLink 2.4.1 का उपयोग कर, यह क्या वास्तव में (पठनीयता के लिए elided कुछ उत्पादन) डीबी को भेजी जाने वाली है

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

ऐसा लगता है कि .in(...) पर सीधे Root पर वांछित परिणाम नहीं है। यदि संस्थाओं का उपयोग सीधे संभव नहीं है, तो मुझे उम्मीद है कि Expression का कुछ प्रकार होगा जो कई कॉलम का प्रतिनिधित्व कर सकता है जो .in(...) पर कॉल के लिए रिसीवर हो सकता है, लेकिन मैं कोई भी नहीं ढूंढ पा रहा हूं।

तो, सवाल यह है कि: यह कैसे ठीक से करता है? या क्या यह जेपीए के साथ बिल्कुल संभव नहीं है? या EclipseLink में बस एक बग है?

उत्तर

2

दिलचस्प प्रयास, और उत्पन्न होने वाला विषम एसक्यूएल, एसक्यूएल ऐसा लगता है कि यह बाईं तरफ सही है, लेकिन सही नहीं है। कृपया इसके लिए एक बग लॉग करें, यह ऐसा कुछ है जिसे समर्थित किया जा सकता है। (इसे 2.5 देव निर्माण में भी आज़माएं, यह काम कर सकता है)।

जेपीए मानदंड एपीआई नेस्टेड सरणी का समर्थन नहीं करता है, इसलिए यह जेपीए स्पेक से परे कुछ भी है।

आप बाईं ओर आईडी फ़ील्ड के लिए पथ अभिव्यक्तियों की एक सूची बना सकते हैं और इसके लिए मानदंडबिल्डर शाब्दिक() अभिव्यक्ति का उपयोग कर सकते हैं, यह काम कर सकता है।

ऐसा करने के लिए जेपीए मानक तरीका ऑब्जेक्ट्स की सूची और या() प्रत्येक ऑब्जेक्ट की आईडी तुलना के लिए अभिव्यक्ति में पुनरावृत्ति करना होगा।

+0

त्वरित प्रतिक्रिया के लिए धन्यवाद। दुर्भाग्यवश, 'CriteriaBuilder.literal()' विधि का उपयोग करके चाल चलती प्रतीत नहीं होती है; वास्तव में, यह एसक्यूएल उत्पन्न करता है जो इससे भी बदतर है: – Daniel

+0

'कहां ((?,?,?,?) IN (?,?,?,?, ...)' - फिर यह वास्तविक पथ और इकाई को बांधने के लिए आगे बढ़ता है ऑब्जेक्ट्स। 'रूट.in()' विधि लगभग सही काम कर रही थी, और यह सहजता से ऐसा लगता है कि यह होना चाहिए कि 'रूट.in()' क्या करना चाहिए, आखिरकार, रूट हमेशा एक इकाई का प्रतिनिधित्व करता है, है ना? दुर्भाग्य से , EclipseLink 2.5 इस प्रोजेक्ट के लिए एक विकल्प नहीं है, क्योंकि हम रिलीज के करीब हैं (बस यहां डुप्लिकेट रिकॉर्ड समस्या से निपटने का प्रयास कर रहे हैं), लेकिन मैं इसे एक स्पिन दूंगा और देख सकता हूं कि यह कुछ समय चाल है या नहीं। यदि नहीं, तो मैं सुझाए गए बग को फाइल करूंगा। – Daniel

+0

मैंने सूची में पुनरावृत्ति करके और विभिन्न पीके कॉलम के लिए एंडेड तुलना वाले ऑर्ड अभिव्यक्तियों की एक लंबी श्रृंखला जोड़कर इसे समाप्त कर दिया - वास्तव में जो मैं बचने की उम्मीद कर रहा था, वास्तव में। यह बहुत बदसूरत है और मैंने कभी भी एक स्थान पर देखा है कि सबसे बड़ी मात्रा में ब्रांड्स का उत्पादन करता है, लेकिन यह काम करता है। चूंकि आपने इसे "स्टैंडए" के रूप में सुझाया है तीसरा रास्ता ", मैं आपके उत्तर को स्वीकार किए जाने के रूप में चिह्नित कर रहा हूं। – Daniel

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