डेटाबेस कनेक्शन - क्या उन्हें पैरामीटर के रूप में पारित किया जाना चाहिए?


11

हमारे पास एक ऐसी प्रणाली है जिसके द्वारा डेटाबेस कनेक्शन को एक सामान्य विधि का उपयोग करके एक बार प्राप्त किया जाता है, और उपयोग किए जाने के लिए संबंधित कक्षा में पास किया जाता है। संदेह है कि डेटाबेस कनेक्शन को विभिन्न वर्गों के लिए पैरामीटर के रूप में पास करने से समस्या पैदा होगी, इसलिए मैं यहां देख रहा हूं कि क्या यह वास्तव में व्यवहार्य है, और क्या इसे करने के लिए कोई बेहतर पैटर्न हैं?

मुझे पता है कि दृढ़ता के लिए कुछ ओआरएम उपकरण हैं लेकिन हम उस में नहीं जा सकते, फिर भी ..

किसी भी प्रतिक्रिया का स्वागत किया है, धन्यवाद।


आप किस तरह की समस्याओं का जिक्र कर रहे हैं? किसको है ये शक? (आप नहीं, मैं मान
लेता

1
डेवलपर को कनेक्शन बंद करने की भूल करने जैसी समस्याएं, आम तौर पर मैं सिर्फ यह देखने की कोशिश कर रहा हूं कि क्या डेटाबेस कनेक्शन को पैरामीटर के रूप में विभिन्न तरीकों से गुजरना एक अच्छा अभ्यास है। हां संदेह दूसरे डेवलपर से आता है।
ipohfly

जवाबों:


8

हाँ एक कनेक्शन के आसपास से गुजरना सुरक्षित है। आप एक बाहरी नियंत्रण ब्लॉक में कनेक्शन को संभालते हैं। इसके बारे में कुछ भी असुरक्षित नहीं है।

असुरक्षित क्या है कोड लिख रहा है जो कनेक्शन की गारंटी नहीं देता है समय पर ढंग से निपटाना ठीक है। एक संसाधन को साफ करने के लिए भूलकर इसे पारित करने के लिए असंबंधित है। आप बस आसानी से कोड लिख सकते हैं जो एक लटकते हुए कनेक्शन को बिना कहीं पास किए छोड़ देता है।

C ++ में, यदि आप स्टैक पर आवंटित करते हैं या स्मार्ट पॉइंटर्स का उपयोग करते हैं, तो आप RAII द्वारा संरक्षित हैं। सी # में एक कठोर नियम बनाएं कि सभी डिस्पोजेबल ऑब्जेक्ट्स (जैसे कनेक्शन) को "ब्लॉक" का उपयोग करके घोषित किया जाए। जावा में कोशिश-आखिर तर्क के साथ सफाई करें। यह सुनिश्चित करने के लिए सभी डेटा लेयर कोड पर कोड समीक्षा करें।

सबसे आम उपयोग-मामला तब है जब आपके पास कई ऑपरेशन हैं जिन्हें कई क्रमपरिवर्तन में जोड़ा जा सकता है। और इनमें से प्रत्येक क्रमपरिवर्तन को एक परमाणु-लेनदेन (सभी सफल या रोलबैक) होने की आवश्यकता है। फिर आपको सभी तरीकों के आसपास लेन-देन (और इसलिए संबंधित कनेक्शन) पास करना होगा।

मान लें कि हमारे पास कई फ़ोबार () क्रियाएं हैं जिन्हें परमाणु-लेनदेन के रूप में विभिन्न तरीकों से जोड़ा जा सकता है।

//example in C#
//outer controlling block handles clean up via scoping with "using" blocks.
using (IDbConnection conn = getConn())
{
    conn.Open();
    using (IDbTransaction tran = conn.BeginTransaction())
    {
        try
        {//inner foobar actions just do their thing. They don't need to clean up.
            foobar1(tran);
            foobar2(tran);
            foobar3(tran);
            tran.Commit();
        }
        catch (Exception ex)
        { tran.Rollback(); }
    }
}//connection is returned to the pool automatically

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

Btw। प्रथम श्रेणी के कार्यों के लिए आपकी भाषा के समर्थन के आधार पर आप फ़ोबार () क्रियाओं की सूची में ले सकते हैं। तो एक फ़ंक्शन क्रियाओं के सभी क्रमपरिवर्तन को संभाल सकता है। प्रत्येक क्रमचय के लिए बाहरी नियंत्रण ब्लॉक के दोहराव को खत्म करना।


इसका उत्तर इस रूप में चिह्नित करना कि यह मुझे और अधिक विचार देता है कि स्थिति
कैसी

6

ऐसा लगता है कि आप डिपेंडेंसी इंजेक्शन के बाद हैं । यही है, पूल किए गए कनेक्शन को एक बार बनाया जाता है और जहां भी इसकी आवश्यकता होती है वहां इंजेक्ट किया जाता है। निश्चित रूप से एक विधि पैरामीटर के माध्यम से कनेक्शन में गुजरना निर्भरता इंजेक्शन का एक तरीका है, लेकिन एक IoC कंटेनर जैसे कि Guice, PicoContainer या Spring एक और (सुरक्षित) तरीका है जिससे आप ऐसा कर सकते हैं।

DI का उपयोग करने का मतलब है कि आप अपने मुख्य व्यवसाय तर्क से दूर - निर्माण, खोलने, उपयोग और कनेक्शन के समापन के आसपास तर्क को लपेट सकते हैं।

स्प्रिंग JDBC एट अल आपके लिए इस तरह का व्यवहार करने के उदाहरण हैं


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

-1। एक कनेक्शन एक बहु-उपयोगकर्ता प्रणाली में फिट नहीं होता है। उपयोगकर्ता की कम मात्रा और तेज़ निष्पादन के कारण यह काम कर सकता है। पूलिंग के साथ, एकल उपयोगकर्ता प्रणाली में भी कनेक्शन ऑब्जेक्ट-एक्शन को तुरंत इंस्टेंट करना बेहतर है।
माइक 30

2

डेटा चीजों के बजाय डेटाबेस चीजों के आसपास से गुजरने से समस्याएं हो सकती हैं। इस हद तक, जब भी यह व्यावहारिक हो, तब तक एक डेटाबेस चीज़ को पास न करें जब तक कि कोई उचित डेटाबेस स्वच्छता की गारंटी न दे।

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

यह सब डेटाबेस, कनेक्शन, कथन, परिणाम सेट और उनके जीवनचक्र का सम्मान नहीं करने से उपजा है।

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


1
+1 डीबी कनेक्शन में सबसे कम समय में संभव होना चाहिए। इसे खोलें, इसका उपयोग करें, इसे जितनी जल्दी हो सके बंद करें। आजकल बहुत सारे कनेक्शन पूल कार्यान्वयन हैं इसलिए कई ऑपरेशन के लिए एक कनेक्शन का उपयोग करके एक झूठी अर्थव्यवस्था। और बग या प्रदर्शन की समस्याओं के लिए एक निमंत्रण (तालिकाओं पर ताले
लगाकर

इन मौजूदा पैटर्न और संरचनाओं में से कुछ के नाम क्या हैं?
डेनियल कपलान

@tieTYT जो सबसे आगे आता है वह डेटा एक्सेस ऑब्जेक्ट है जो डेटाबेस को बाकी एप्लिकेशन से छिपाने का काम करता है। डेटा एक्सेस लेयर और ऑब्जेक्ट-रिलेशनल मैपिंग

जब मैं उन पैटर्नों के बारे में सोचता हूं तो मुझे लगता है कि वे जो कुछ पूछ रहे हैं, उससे कहीं अधिक उच्च स्तर पर हैं। मान लीजिए कि आपको Rootडाओ से प्राप्त करने का एक तरीका मिल गया है । लेकिन तब आपको एहसास होता है कि आप इसके साथ Nodeपूरी Rootवस्तु को बाहर निकाले बिना एक रास्ता भी चाहते हैं । आप RootDao कॉल को NodeDao कोड कैसे बनाते हैं (यानी: reuse), लेकिन सुनिश्चित करें कि NodeDao केवल तभी कनेक्शन बंद करता है जब NodeDao को सीधे कॉल किया जाता है और Dao के कॉल करने पर कनेक्शन खुला रहता Rootहै?
डेनियल कपलान

1
बस यह जोड़ना चाहता था कि यदि आप ऑटो-कम मोड में नहीं हैं, तो एक कनेक्शन पास करने से ऐसी स्थिति आ सकती है जहां एक ऑब्जेक्ट डेटाबेस को अपडेट करता है, तो दूसरे (संभवतः असंबंधित) ऑब्जेक्ट को कनेक्शन मिल जाता है, एक त्रुटि होती है, और हवा उठती है। पहली वस्तु के परिवर्तनों को वापस करना। इस प्रकार की त्रुटियां डीबग करना बहुत कठिन हो सकता है ।
TMN

2

Connectionआस- पास के उदाहरणों को पारित करना आम तौर पर एक समस्या नहीं है, भले ही ज्यादातर स्थिति में केवल डीएओ कार्यान्वयन के लिए उनके साथ कुछ भी करना चाहिए। अब, आपकी समस्या के उपयोग के बाद कनेक्शन बंद नहीं होने के बारे में होने के कारण, इसे ठीक करना आसान है: Connectionऑब्जेक्ट को उसी स्तर पर बंद करने की आवश्यकता होती है जिसे इसे खोला जाता है, अर्थात उसी विधि में। मैं व्यक्तिगत रूप से निम्नलिखित कोड पैटर्न का उपयोग करता हूं:

final Connection cnx = dataSource.getConnection();
try {
    // Operations using the instance
} finally {
    cnx.close();
}

इस तरह से मैं सुनिश्चित करता हूं कि सभी कनेक्शन हमेशा बंद रहें, भले ही एक अपवाद ब्लॉक के भीतर फेंक दिया गया हो। मैं वास्तव में जब तक Statementऔर ResultSetउदाहरणों के लिए सटीक समान पैटर्न का उपयोग कर रहा हूं , और अब तक सब कुछ सुचारू रूप से चल रहा है।

2018-03-29 को संपादित करें: जैसा कि नीचे दिए गए टिप्पणियों में user1156544 द्वारा संकेत दिया गया है, जावा 7 से शुरू करके कोशिश के साथ-साथ संसाधनों के निर्माण का उपयोग किया जाना चाहिए। इसका उपयोग करते हुए, मैंने अपने प्रारंभिक उत्तर में दिए गए कोड पैटर्न को सरल बनाया जा सकता है:

try (final Connection cnx = dataSource.getConnection()) {
    // Operations using the instance
}

1
मैं कुछ इसी तरह का उपयोग करता हूं। मेरे पास फ़ंक्शन doInTransaction (DbTask कार्य) है, जहां DbTask कनेक्शन पैरामीटर के साथ विधि के साथ मेरा इंटरफ़ेस है। doInTransaction कनेक्शन प्राप्त करता है, कॉल टास्क और कमिट (या रोलबैक यदि कोई अपवाद था) और उस कनेक्शन को बंद कर दें।
user470365

आपके उदाहरण से देखते हुए, इसका मतलब होगा कि डेटा स्रोत ऑब्जेक्ट एक सिंगलटन है?
ipohfly

@ipohfly वास्तव में मुझे लगता है कि वस्तु नामित किया जाना चाहिए था dataSourceन कि DataSource(मैं अपने जवाब यह है कि बिंदु के बारे में ठीक कर देंगे)। उस वस्तु का सटीक प्रकार होगा javax.sql.DataSource। पुराने कोड में, मैं अपने अनुप्रयोगों के भीतर सभी उपलब्ध डेटा स्रोतों का प्रबंधन करने के लिए एक सिंगलटन का उपयोग करता था। मेरे DAO को इस बारे में पता नहीं था, क्योंकि DataSourceउदाहरण निर्भरता इंजेक्शन के माध्यम से प्रदान किया जाता है।
केविनएलएच

यदि आप इस स्कीमा का उपयोग करते हैं, तो try-with-
Resources का

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

0

एक सिंगलटन का उपयोग करने के बजाय इस तरह से चीजें करने के लिए एक ट्रेडऑफ़ है जिसे आप आवश्यकतानुसार प्राप्त कर सकते हैं। मैंने अतीत में दोनों तरह से चीजें की हैं।

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

दूसरी ओर, मान लीजिए कि आपको कनेक्शन के एक पूल का प्रबंधन करने की आवश्यकता है जहां किसी दिए गए कॉल को किसी भी मनमाने कनेक्शन का उपयोग करने की आवश्यकता हो सकती है। उदाहरण के लिए, कई सर्वरों में वितरित लेनदेन करते समय ऐसा हो सकता है। इस मामले में आप आमतौर पर डीबी कनेक्शन ऑब्जेक्ट को पास करने से बेहतर होते हैं, जबकि आप एकल के साथ काम कर रहे हैं। मुझे लगता है कि यह आम तौर पर दुर्लभ मामला है, लेकिन जब आपको जरूरत होती है तो ऐसा करने में कुछ भी गलत नहीं है।

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