2013-05-08 11 views
8

में एक चरम बनाम एक चरम बनाम पैरामीटर एक्सप्रेशन का उपयोग करते हुए जेपीए मानदंड एपीआई का उपयोग करते समय, एक चर पर पैरामीटर एक्सप्रेशन का उपयोग करने का क्या फायदा है? जैसे जब मैं एक स्ट्रिंग वैरिएबल में नाम से ग्राहक की खोज करना चाहते हैं, मैं मानकों के साथ की तरहजेपीए मानदंड एपीआई

private List<Customer> findCustomer(String name) { 
    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class); 
    Root<Customer> customer = criteriaQuery.from(Customer.class); 
    criteriaQuery.select(customer).where(cb.equal(customer.get("name"), name)); 
    return em.createQuery(criteriaQuery).getResultList(); 
} 

कुछ लिख सकता है यह हो जाता है:

private List<Customer> findCustomerWithParam(String name) { 
    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class); 
    Root<Customer> customer = criteriaQuery.from(Customer.class); 
    ParameterExpression<String> nameParameter = cb.parameter(String.class, "name"); 
    criteriaQuery.select(customer).where(cb.equal(customer.get("name"), nameParameter)); 
    return em.createQuery(criteriaQuery).setParameter("name", name).getResultList(); 
} 

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

+0

मैं सामान्य रूप में जेपीए के लिए नहीं बोल सकता बनाने , लेकिन मुझे पता चला कि ओपनजेपीए आंतरिक रूप से एक मानदंड क्वेरी को जेपीक्यूएल में परिवर्तित करता है और इसे ओपनजेपीए-विशिष्ट कार्यक्षमता का उपयोग करके मुद्रित किया जा सकता है (देखें p: //openjpa.apache.org/builds/2.1.1/apache-openjpa/docs/ch13s03.html)। पहली क्वेरी "ग्राहक सी से चुनें सी WHERE c.name = 'test ग्राहक'" का अनुवाद करती है। इसका अर्थ यह है कि यह पैरामीटर का उपयोग नहीं करता है, इसलिए अगर इसे SQL में आगे अनुवादित किया जाता है तो संबंधित तैयार कथन पैरामीटर का उपयोग नहीं करेगा। दूसरा संस्करण जेपीक्यूएल में अनुवाद करता है "ग्राहक सी से चुनें सी WHERE c.name =: name", इसलिए मैं पैरामीटर का उपयोग करूंगा। –

+0

कुछ और परीक्षणों के बाद मैंने पाया कि जेपीक्यूएल के साथ एक ही प्रश्न लिखना और नाम '' या 'x' = 'x' का उपयोग करके जेपीक्यूएल इंजेक्ट करता है। मानदंड API का उपयोग करते समय, उत्पन्न जेपीक्यूएल जो ओपनजेपीए लॉग बिल्कुल दिखता है। हालांकि ओपनजेपीए द्वारा लॉग इन किया गया वास्तविक एसक्यूएल जेपीक्यूएल मामले में '' 'या' x '=' x 'के पैरामीटर के साथ एक तैयार कथन का उपयोग करता है।इसका मतलब है कि एसक्यूएल इंजेक्शन यहां काम नहीं करता है! दुर्भाग्य से मुझे नहीं पता कि यह कितना विश्वसनीय है। ऐसा लगता है कि यह एक अनियंत्रित सुविधा है। –

+0

युक्ति: मैंने अभी http://www.querydsl.com/ को आज़माया है और यह वाक्यविन्यास बहुत संक्षिप्त और पठनीय है। ऐसा लगता है कि डिफ़ॉल्ट रूप से पैरामीटर का उपयोग करके एसक्यूएल इंजेक्शन के खिलाफ सुरक्षा होती है। –

उत्तर

0

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

एसक्यूएल इंजेक्शन हमेशा डेवलपर को नीचे आता है कि क्या वे पैरामीटर के रूप में उपयोग किए जा रहे कुछ उपयोगकर्ता इनपुट को मान्य करते हैं या नहीं।

+0

यह जानना एक अच्छी बात है। मैं अनुकूलित कोड के ऊपर सरल कोड पसंद करता हूं जब तक कि इसे किसी समस्या के रूप में पहचाना नहीं जाता है। वैकल्पिक मानदंडों के लिए पैरामीटर का उपयोग करने के साथ मेरे पास समस्या है जहां खंड है कि पैरामीटर घोषित करने और सेट करने के लिए आपको "if (वैकल्पिक पैरामीटर! = Null)" जैसे दोहराए गए कोड की आवश्यकता है। आपका दूसरा जवाब मुझे भ्रमित करता है। मैंने हमेशा सोचा कि (संभव कार्यान्वयन कीड़े तक) पैरामीटर को एसक्यूएल इंजेक्शन हमलों से पीड़ित होने की गारंटी नहीं थी और मैं सोच रहा था कि मेरा सरल पहला तरीका एसक्यूएल इंजेक्शन से पीड़ित हो सकता है या नहीं। मैं ओपनजेपीए का उपयोग कर रहा हूं। –

0

आप इस तरह ParameterExpression उपयोग कर सकते हैं: मान लें कि आप कुछ इनपुट फ़िल्टर है, एक उदाहरण यह हो सकता है:

    अपने प्रश्न में
  • आप एक वित्तीय संहिता के मूल्य की जाँच करने के लिए है।

चलो शुरू करते हैं: सब से पहले criteriaQuery और criteriaBuilder और जड़

 CriteriaBuilder cb = _em.getCriteriaBuilder(); 
     CriteriaQuery<Tuple> cq = cb.createTupleQuery(); 
     Root<RootEntity> soggettoRoot = cq.from(RootEntity.class); 

1) एक predicateList inizialize (जहां खंड के लिए उपयोग) और एक paramList (परम के लिए उपयोग बनाने)

Map<ParameterExpression,String> paramList = new HashMap(); 
List<Predicate> predicateList = new ArrayList<>(); 

) जांचें कि इनपुट एन है या नहीं ull और बनाने predicateList और परम

if(input.getFilterCF() != null){ 
      //create ParameterExpression 
      ParameterExpression<String> cf = cb.parameter(String.class); 


      //if like clause 
      predicateList.add(cb.like(root.<String>get("cf"), cf)); 
      paramList.put(cf , input.getFilterCF() + "%"); 

      //if equals clause 
      //predicateList.add(cb.equal(root.get("cf"), cf)); 
      //paramList.put(cf,input.getFilterCF()()); 
     } 

) जहां खंड

cq.where(cb.and(predicateList.toArray(new Predicate[predicateList.size()]))); 
TypedQuery<Tuple> q = _em.createQuery(cq); 

) सेट परम मूल्य

 for(Map.Entry<ParameterExpression,String> entry : paramList.entrySet()) 
     { 
      q.setParameter(entry.getKey(), entry.getValue()); 
     } 
+0

पैरामीटर का उपयोग नहीं होने पर एसक्यूएल इंजेक्शन संभव होगा? – Alex78191

+0

हाँ, यह संभव होगा –

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