पूल में JDBC कनेक्शन बंद करना


109

JDBC का उपयोग करने के लिए हमारा मानक कोड अनुभाग है ...

Connection conn = getConnection(...);
Statement  stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
ResultSet  rset = stmt.executeQuery (sqlQuery);

// do stuff with rset

rset.close(); stmt.close(); conn.close();

प्रश्न 1: कनेक्शन पूल का उपयोग करते समय, क्या किसी को अंत में कनेक्शन बंद करना चाहिए? यदि हां, तो पूलिंग का उद्देश्य क्या नहीं है? और यदि नहीं, तो जब कनेक्शन का एक विशेष उदाहरण मुक्त हो जाता है और पुन: उपयोग किया जा सकता है तो डेटा स्रोत कैसे जानता है? मैं इस एक पर थोड़ा उलझन में हूँ, किसी भी संकेत की सराहना की।

प्रश्न 2: निम्नलिखित विधि मानक के करीब कुछ भी है? ऐसा लगता है कि पूल से एक कनेक्शन प्राप्त करने का प्रयास किया जा रहा है, और यदि डेटासोर्स स्थापित नहीं किया जा सकता है, तो पुराने ज़माने के DriverManager का उपयोग करें। हम यह भी सुनिश्चित नहीं कर रहे हैं कि रनटाइम में किस हिस्से को निष्पादित किया जा रहा है। ऊपर दिए गए प्रश्न को दोहराते हुए, क्या इस तरह की विधि से आने वाले कनेक्शन को बंद करना चाहिए?

साभार, - एम.एस.

synchronized public Connection getConnection (boolean pooledConnection)
                                                        throws SQLException {
        if (pooledConnection) {
                if (ds == null) {
                        try {
                                Context envCtx = (Context)
                                        new InitialContext().lookup("java:comp/env");
                                ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
                                return ds.getConnection();
                        } catch (NamingException e) {
                                e.printStackTrace();
                }}
                return (ds == null) ? getConnection (false) : ds.getConnection();
        }
        return DriverManager.getConnection(
                "jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}

संपादित करें: मुझे लगता है कि हम जमा हुए कनेक्शन प्राप्त कर रहे हैं क्योंकि हम एक स्टैक ट्रेस नहीं देखते हैं।

जवाबों:


121

कनेक्शन पूल का उपयोग करते समय, क्या किसी को अंत में कनेक्शन बंद करना चाहिए? यदि हां, तो पूलिंग का उद्देश्य क्या नहीं है? और यदि नहीं, तो जब कनेक्शन का एक विशेष उदाहरण मुक्त हो जाता है और पुन: उपयोग किया जा सकता है तो डेटा स्रोत कैसे जानता है? मैं इस एक पर थोड़ा उलझन में हूँ, किसी भी संकेत की सराहना की।

हां, निश्चित रूप से आपको पूल किए गए कनेक्शन को भी बंद करने की आवश्यकता है। यह वास्तव में वास्तविक कनेक्शन के आसपास एक आवरण है। यह कवर के तहत wil पूल में वास्तविक कनेक्शन जारी करता है। यह तय करने के लिए पूल के आगे है कि क्या वास्तविक कनेक्शन वास्तव में बंद हो जाएगा या एक नए getConnection()कॉल के लिए पुन: उपयोग किया जाएगा । इसलिए, भले ही आप कनेक्शन पूल का उपयोग कर रहे हों या नहीं, आपको हमेशाfinally ब्लॉक के ब्लॉक में उल्टे क्रम में सभी JDBC संसाधनों को बंद करना चाहिए, tryजहां आपने उन्हें अधिग्रहित किया है। Java 7 में try-with-resourcesस्टेटमेंट का उपयोग करके इसे और सरल बनाया जा सकता है ।


निम्नलिखित विधि कुछ भी मानक के करीब है? ऐसा लगता है कि पूल से एक कनेक्शन प्राप्त करने का प्रयास किया जा रहा है, और यदि डेटासोर्स स्थापित नहीं किया जा सकता है, तो पुराने ज़माने के DriverManager का उपयोग करें। हम यह भी सुनिश्चित नहीं कर रहे हैं कि रनटाइम में किस हिस्से को निष्पादित किया जा रहा है। ऊपर दिए गए प्रश्न को दोहराते हुए, क्या इस तरह की विधि से आने वाले कनेक्शन को बंद करना चाहिए?

उदाहरण बहुत डरावना है। आपको बस DataSourceएक बार आवेदन करने वाले के स्टार्टअप के दौरान कुछ कंस्ट्रक्टर / एप्लिकेशनलीड डीबी कॉन्फिगरेशन क्लास के इनिशियलाइजेशन / लुकअप / इनिशियलाइज़ करने की आवश्यकता है । तो बस getConnection()एक और एक ही datasource आवेदन के जीवन भर में बुलाओ । न तो सिंक्रोनाइजेशन की जरूरत है और न ही नलकूपों की।

यह सभी देखें:


Thats यह क्या कर रहा है (एक बार आरंभ करें), यह नहीं है? ds एक उदाहरण चर है, और यदि (ds == null) ... आरंभीकरण हिस्सा है।
मनिदीप सेनगुप्ता

चेक को हर बार गेट -मेथड की तरह getConnection()करना अजीब है। बस इसे तुल्यकालन / nullchecks के बिना एक ही वर्ग के c'tor या initialization ब्लॉक में करें। यह केवल एक बार बुलाया जाएगा। अधिक संकेत और किकऑफ उदाहरणों के लिए, आपको यह लेख उपयोगी लग सकता है।
BalusC

बहुत बढ़िया लेख, BalusC। क्लास मैं डीटीओ का उपयोग करके डेटा लेयर के बहुत अधिक कार्यान्वयन के साथ काम कर रहा हूं। मैं आपसे सहमत हूं, आरंभीकरण निर्माणकर्ता में होना चाहिए। अब, इस वर्ग में कई तरीके हैं, जिनमें से प्रत्येक में स्थानीय चर के रूप में कॉन, stmt और rset हैं, कनेक्शन एक कोशिश ब्लॉक में हैं, और अंत में एक 1-लाइन कॉल csrClose (कॉन, stmt, rset) है, जहां सभी 3 हैं बंद हैं (रिवर्स ऑर्डर में)। अब, आप जिस डीटीओ के उदाहरण में विकसित होते हैं वह एक डीबी टेबल पंक्ति की दर्पण छवि है। हमारे पास जॉइन (और अन्य क्लॉज़) के साथ जटिल एसक्यूएल प्रश्न हैं, क्या आपके पास इस तरह के परिणामों के लिए डीएओ को विकसित करने के बारे में एक लेख है?
मणिदीप सेनगुप्ता

2
@yat: आप close()उन सभी को finallyउसी tryब्लॉक के ब्लॉक में कॉल करें जहां आपने उन्हें अधिग्रहित / बनाया है। यह पूरी तरह से परवाह किए बिना कि यह एक जमा कनेक्शन है या नहीं।
बालुस 16

1
@ आईजावा: उस पूल को एक शौकिया द्वारा लिखा गया है, जिसे कोई भी पता नहीं है कि वह क्या कर रहा है। इसे अनदेखा करें और एक वास्तविक पुस्तकालय के लिए जाएं। जैसे हिकारीपी।
बालूसक

22

पूल आम तौर पर आपको एक लिपटे हुए कनेक्शन ऑब्जेक्ट को लौटाते हैं, जहां क्लोज़ () विधि ओवरराइड होती है, आमतौर पर कनेक्शन को पूल में लौटाते हैं। पास बुलाना () ठीक है और शायद अभी भी आवश्यक है।

एक करीब () विधि शायद इस तरह दिखेगी:

public void close() throws SQLException {
  pool.returnConnection(this);
}

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


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

1
Calling close() is OK and probably still required., कॉल को बंद करने से कनेक्शन लीक नहीं होगा, जब तक कि पूल कुछ रिकवरी रणनीति को लागू नहीं करता है
सरोगेट

0

वास्तव में, कनेक्शन प्रबंधन के लिए सबसे अच्छा तरीका यह है कि उन्हें कहीं भी किसी भी कोड से न जोड़ा जाए।

एक SQLExecutor वर्ग बनाएँ जो एक और एकमात्र स्थान है जो कनेक्शन खोलता और बंद करता है।

आवेदन के पूरे बाकी तो पूल से कनेक्शन पाने के बजाय निष्पादक में बयान देते हैं और सभी जगह उन्हें प्रबंधित (या गलत तरीके से) करते हैं।

आप निष्पादनकर्ता के जितने चाहें उतने उदाहरण हो सकते हैं, लेकिन कोई भी ऐसा कोड नहीं लिखना चाहिए जो अपनी ओर से कनेक्शन खोलता और बंद करता हो।

आसानी से, यह आपको कोड के एक सेट से अपने सभी एसक्यूएल को लॉग करने देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.