2012-10-18 17 views
12

जावा में जेडीबीसी का उपयोग करते समय, डेटाबेस से पूछताछ करने की आम तौर पर स्वीकृत विधि कनेक्शन प्राप्त करना है, उस कनेक्शन से एक कथन बनाएं, और फिर उस कथन से एक क्वेरी निष्पादित करें।डेटाबेस को कई बार पूछने का पसंदीदा तरीका?

// load driver 
Connection con = DriverManager.getConnection(..); 
Statement stmt = con.createStatement(); 
ResultSet result = stmt.executeQuery("SELECT.."); 
// ... 

हालांकि, मुझे एक ही डेटाबेस में दूसरी क्वेरी का इलाज करने के बारे में अनिश्चितता है।

  1. किसी अन्य क्वेरी ही Statement वस्तु पर सुरक्षित रूप से क्रियान्वित किया जा सकता है, या एक और बयान आदेश किसी अन्य क्वेरी को निष्पादित करने में Connection वस्तु से बनाया जाना चाहिए?

  2. ही Statement वस्तु कई प्रश्नों के लिए इस्तेमाल किया जा सकता है, तो क्या Statement वर्ग का उद्देश्य है (क्योंकि यह तो अधिक भावना के लिए एक Connection.executeQuery() विधि अस्तित्व के लिए होगा)?

+4

पहले भाग के लिए, क्या आपने इसे स्वयं करने का प्रयास किया? क्या आपको कोई अपवाद या कोई अवांछित आउटपुट मिला? –

+1

वेब में कई उदाहरण हैं। आप उन्हें वहां देख सकते थे, अपने आप को आजमाएं और यदि आपको अपवाद मिलता है या परेशानी होती है तो आपके प्रश्न में सुधार होता है, इसलिए हम आपकी अधिक सटीक मदद कर सकते हैं। – user

+0

@ रोहितजैन मेरे पास नहीं है, लेकिन मैं निश्चित हूं कि एक ही वक्तव्य विकल्प से कई प्रश्न निष्पादित किए जा सकते हैं, जिससे मुझे आश्चर्य होता है कि ऐसा करने में कोई कमी या सुरक्षा चिंताएं हैं (प्रश्न 1), और नतीजतन , स्टेटमेंट क्लास का बिंदु क्या है (प्रश्न 2)। – Vulcan

उत्तर

7

हाँ आप Statement वस्तु का पुन: उपयोग कर सकते हैं, लेकिन ResultSet वस्तुओं executeQuery द्वारा लौटाए गए पहले से ही resultsets खोला बंद करता है।

स्पष्टीकरण

डिफ़ॉल्ट रूप से के लिए javadoc देखें, वक्तव्य वस्तु में केवल एक ResultSet वस्तु खुला एक ही समय में हो सकता है। इसलिए, यदि एक परिणामसेट ऑब्जेक्ट का पठन किसी अन्य के पढ़ने के साथ इंटरलीव किया गया है, तो प्रत्येक को विभिन्न स्टेटमेंट ऑब्जेक्ट्स द्वारा उत्पन्न किया जाना चाहिए। स्टेटमेंट इंटरफ़ेस में सभी निष्पादन विधियां एक खुला एक मौजूद होने पर एक स्टेटमेंट की वर्तमान परिणामसेट ऑब्जेक्ट को पूर्ण रूप से बंद करें।

तो निम्नलिखित होता है:

// load driver 
Connection con = DriverManager.getConnection(..); 
Statement stmt = con.createStatement(); 
ResultSet result = stmt.executeQuery("select .."); 
// do something with result ... or not 
ResultSet result2 = stmt.executeQuery("select ..."); 
// result is now closed, you cannot read from it anymore 
// do something with result2 
stmt.close(); // will close the resultset bound to it 

उदाहरण के लिए आप jTDS परियोजना में वक्तव्य का एक खुला स्रोत कार्यान्वयन पा सकते हैं। में Statement.executeQuery() method आप initialize() के लिए एक कॉल देख सकते हैं कि closes all the resultsets पहले से ही

protected void initialize() throws SQLException { 
    updateCount = -1; 
    resultQueue.clear(); 
    genKeyResultSet = null; 
    tds.clearResponseQueue(); 
    // FIXME Should old exceptions found now be thrown instead of lost? 
    messages.exceptions = null; 
    messages.clearWarnings(); 
    closeAllResultSets(); 
} 
+0

यदि सभी निष्पादन विधियां एक कथन के वर्तमान परिणामसेट (अगर खुली हैं) को पूर्ण रूप से बंद कर देती हैं, तो क्या किसी अन्य क्वेरी को निष्पादित करने से पहले परिणामसेट को स्पष्ट रूप से बंद करना आवश्यक है? – Vulcan

+0

@ वल्कन आप सही हैं, जैसा कि आपने देखा है और जैसा कि यह जावाडोक में कहा गया है, 'स्टेटमेंट' पर 'execute *()' विधियों को किसी भी खुले 'परिणामसेट' को बंद करना प्रतीत होता है, इसलिए व्यवहार में यह है नया निष्पादन जारी करने से पहले 'क्लोज़()' पर कॉल करना अनिवार्य नहीं है, लेकिन आपके द्वारा खोले गए संसाधनों को बंद करना अच्छा अभ्यास है। – Alex

+0

उदाहरण के रूप में जेटीडीएस ओपन सोर्स कार्यान्वयन के लिए मेरा संपादन देखें। – Alex

1

खोला खैर यही कारण है कि हम वस्तु उन्मुख प्रोग्रामिंग में कक्षाओं की अवधारणा है है। एक वर्ग घटक सदस्यों को परिभाषित करता है जो अपने उदाहरणों को राज्य और व्यवहार के लिए सक्षम बनाता है। यहां कथन एक एसक्यूएल कथन से संबंधित सब कुछ के साथ सौदा करता है। बहुत अधिक समारोह है कि एक बैच प्रश्नों आदि

3

प्रोग्राम की तरह प्रदर्शन कर सकते हैं कर रहे हैं, आप एक ही कनेक्शन और एक से अधिक क्वेरी के लिए एक ही बयान पुन: उपयोग और बयान और अंत में कनेक्शन बंद कर सकते हैं।

हालांकि, यह एक अच्छा अभ्यास नहीं है। एप्लिकेशन का प्रदर्शन डेटाबेस के उपयोग के तरीके से बहुत संवेदनशील है। आदर्श रूप में, प्रत्येक कनेक्शन कम से कम समय के लिए खुला होना चाहिए। फिर, कनेक्शन पूल किया जाना चाहिए। इसके द्वारा आप प्रत्येक क्वेरी को {open connection, create a prepared statement, run query, close statement, close connection} के ब्लॉक में संलग्न करेंगे। यह भी तरीका है कि अधिकांश एसक्यूएल टेम्पलेट्स लागू किए जाते हैं। यदि समवर्ती परमिट की अनुमति है, तो आप एक ही समय में थ्रेड पूल का उपयोग करके ऐसे कई प्रश्नों को आग लगा सकते हैं।

+0

उचित लगता है, लेकिन कम से कम समय के लिए कनेक्शन को खोलने के पीछे तर्क क्या है? 10 मिनट प्रति मिनट को संभालने के लिए एक कनेक्शन खुला रखना बेहतर है, या प्रत्येक 6 सेकंड में एक बार एक नया कनेक्शन खोलना बेहतर है? – Vulcan

+0

@ वल्कन यह वही नहीं है। आपके पास कनेक्शन कम से कम समय खुलता है और फिर आप इसे वापस पूल में वापस कर देते हैं। पूल आपके लिए कनेक्शन खुला रखेगा। क्योंकि जब भी आप सुनिश्चित होते हैं कि यह हमेशा पूल में वापस आ जाता है तो आप कनेक्शन को "बंद" करते हैं। यदि आप इसे स्वयं संभालते हैं, तो जोखिम बढ़ता है कि आप बंद होने से चूक जाते हैं और डेटाबेस सत्र या मेमोरी लीक समस्याओं में भाग लेते हैं। –

1

आमतौर पर, यह एक प्रश्न के लिए एक कथन है।ऐसा करने के लिए आवश्यक नहीं हो सकता है लेकिन वास्तविक एप्लिकेशन लिखते समय, आप बार-बार वही कदम दोहराना नहीं चाहते हैं। यह डीआरवाई प्रिंसिपल के खिलाफ है, साथ ही एप्लिकेशन बढ़ने के साथ ही यह अधिक जटिल हो जाएगा।

ऑब्जेक्ट्स लिखना अच्छा होता है जो उस तरह के निम्न स्तर (दोहराव) सामान को संभालेगा, और प्रश्न प्रदान करके डीबी तक पहुंचने के लिए विभिन्न विधियां प्रदान करेगा।

1

मैं नए बयान बनाने के बारे में चिंता नहीं करता। हालांकि डेटाबेस कनेक्शन खोलना संसाधन गहन हो सकता है और उद्घाटन और समापन कनेक्शन प्रभाव प्रदर्शन करता है।

कुछ आत्म प्रबंधन तरीके से कनेक्शन छोड़ना आम तौर पर बहुत खराब है।

आपको connection pooling का उपयोग करने पर विचार करना चाहिए। आप आमतौर पर एक करीबी कमांडो जारी करते हैं, हालांकि आप केवल उस कनेक्शन को पूल में ही दे रहे हैं। जब आप एक नए कनेक्शन का अनुरोध करते हैं तो यह आपके द्वारा पहले दिए गए कनेक्शन का पुन: उपयोग करेगा।

आप एक कनेक्शन के लिए अलग-अलग बयान लेना चाहेंगे। वक्तव्य एक कार्यान्वयन और एक इंटरफ़ेस है। आपको जिस चीज की आवश्यकता है उसके आधार पर कभी-कभी CallableStatment का उपयोग करना चाहते हैं। आवश्यकता होने पर कुछ तर्कों का पुन: उपयोग किया जा सकता है।

+0

धन्यवाद, मुझे पहले कभी कनेक्शन पूलिंग का सामना नहीं करना पड़ेगा, और ऐसा लगता है कि मैं अपने सर्वर एप्लिकेशन में उपयोग कर रहा हूं। – Vulcan

+0

@ वल्कन यदि सर्वर एप्लिकेशन एक वेब एप्लिकेशन है तो एप्लिकेशन सर्वर कनेक्शन पूलिंग कर सकता है। कॉन्फ़िगरेशन आपके एप्लिकेशन सर्वर में लिखा जाना चाहिए। अन्यथा आप http://commons.apache.org/dbcp/ या अपनी पसंद के कुछ अन्य टूलसेट का उपयोग कर सकते हैं। –

+0

मेरी माफ़ी, मुझे विश्वास नहीं है कि मैं उस कथन से स्पष्ट था; यह क्लाइंट सॉकेट के लिए कनेक्ट करने के लिए बस एक सर्वर सॉकेट होस्ट करने वाला जावा एप्लिकेशन है। – Vulcan

2

मेरे पास एक थ्रेड किए गए वातावरण में कनेक्शन और कथन का उपयोग करने के लिए एक चीज है। मेरा अनुभव दिखाता है कि stmt.executeQuery (..) समानांतर वातावरण में उपयोग करने के लिए सहेजता है लेकिन परिणामस्वरूप प्रत्येक क्वेरी को क्रमबद्ध किया जाता है और इस प्रकार अनुक्रमिक रूप से संसाधित किया जाता है, कोई भी गति-अप नहीं प्रदान करता है। तो यह प्रत्येक थ्रेड के लिए एक नया कनेक्शन (स्टेटमेंट नहीं) का उपयोग करने के लिए बेहतर होगा।

मानक अनुक्रमिक वातावरण के लिए मेरे अनुभव से पता चला है कि राज्यों का पुन: उपयोग करने में कोई समस्या नहीं है और परिणामसेट को मैन्युअल रूप से बंद नहीं किया जाना चाहिए।

+0

मुझे यह बेहद सहायक पाया गया है, क्योंकि मैं एक थ्रेडेड वातावरण में कनेक्शन और स्टेटमेंट का उपयोग कर रहा हूं। * उडो हेल्ड * के उत्तर के साथ क्या सलाह है, मुझे लगता है कि मैंने सीखा है कि मुझे बहु-थ्रेडेड डेटाबेस कनेक्शन के लिए क्या चाहिए। – Vulcan

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