2009-04-21 13 views
22

तो मुझे यह सामान्य डीएओ चीज चल रही है और चेहरे की कीमत पर यह ठीक प्रतीत होता है। यह मूल रूप से Hibernate लोगों से CaveatEmptor नमूना आवेदन के बाद मॉडलिंग किया गया है।डीएओ पैटर्न - लेनदेन कहां फिट होते हैं?

इसके ऊपर मेरे पास एक व्यापार परत है ... आवेदन की हिम्मत। यह किसी भी विशिष्ट डीएओ कार्यान्वयन से पूरी तरह से अनजान है।

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

मैं तो यहाँ, शुरू करने, और रोलबैक के तरीकों और मेरे व्यापार परत को एक कार्यान्वयन पारित के साथ एक सरल लेनदेन इंटरफ़ेस बना सकते हैं ... लेकिन ... मुझे यकीन है कि नहीं कर रहा हूँ ...

है चुनौती: क्या आप स्प्रिंग (या ईजेबी, या कोई अन्य अतिरिक्त ढांचा) शब्द का उपयोग किए बिना ऐसा करने के लिए मेरे लिए एक तरीका सुझा सकते हैं?

उत्तर

12

मुझे याद है कि Martin Fowler व्यापार परत में लेनदेन के नियंत्रण को रखने के लिए सलाह है क्योंकि लेनदेन एक व्यावसायिक समस्या है। (यदि आप बैंक खाता श्रेणी तैयार करते हैं, तो लेनदेन डोमेन भाषा का हिस्सा होता है)।

आप एक TransactionScope लागू करने के लिए .NET में के रूप में यह है कि

using (TransactionScope ts = new TransactionScope()) 
{ 
    ... 
} 

यह रूप में (वास्तव में नहीं है, लेकिन अगर आप एक जावा पुरुष हैं, यह आप के लिए और अधिक स्पष्ट है) एक ही बात है की तरह कुछ काम करता है की कोशिश कर सकते

TransactionScope scope = new TransactionScope(); 
try 
{ 
... 
scope.Commit(); 
} 
catch(Exception ex) 
{ 
    scope.Rollback(); 
    throw; 
} 

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

ITransactionScope scope = transactionFactory.CreateTransaction(); 
try 
{ 
... 
scope.Commit(); 
} 
catch(Exception ex) 
{ 
    scope.Rollback(); 
    throw; 
} 
+0

अच्छा, यह काम करता है, लेकिन आप किसी यथार्थवादी व्यावसायिक ऐप के लिए कोड की हजारों डुप्लिकेट लाइनों के साथ जल्दी से समाप्त होते हैं। –

+0

@Rogerio, किसी व्यापार ऑब्जेक्ट में हर विधि आवश्यक रूप से एक लेनदेन नहीं है। यदि आप डुप्लिकेशन के साथ समाप्त होते हैं, तो हो सकता है कि आपका डोमेन अच्छी तरह से व्यक्त न हो, या आप इसे व्यक्त करने का एक बेहतर तरीका ढूंढ सकें। –

+3

मैंने पीओईएए पुस्तक (71-77) में लेनदेन के बारे में प्रासंगिक पृष्ठों को फिर से पढ़ा है, और लेखक व्यवसाय की समस्या होने के लेनदेन के बारे में ऐसी कोई बात नहीं सलाह देते हैं (वे * व्यापार भाषा का हिस्सा नहीं हैं, बल्कि एक उपकरण *समरूपता नियंत्रण*)। साथ ही, व्यावहारिक रूप से व्यवसाय संचालन में शामिल लगभग हर विधि * सिस्टम लेनदेन के संदर्भ में चलनी चाहिए, भले ही आपके पास आमतौर पर प्रत्येक विधि के लिए अलग लेनदेन न हो। बिंदु बनी हुई है, एक अच्छी तरह से डिज़ाइन किया गया एप्लिकेशन * हर जगह स्पष्ट लेनदेन सीमा कोड नहीं होना चाहिए, बल्कि केवल एक या दो केंद्रीय स्थानों में होना चाहिए। –

1

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

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

यह कक्षा तब लेनदेन शुरू करने और प्रतिबद्ध करने के लिए nHibernate के सत्र के साथ काम करती है।

1

अतीत में मैंने डीएओ के पदानुक्रम के लिए रूट डीएओ में लेनदेन तर्क डाल दिया है जो आपके मॉडल में ऑब्जेक्ट्स के पदानुक्रम से मेल खाता है जो सिस्टम में एक ठोस इकाई का प्रतिनिधित्व करता है।

आई, यदि आपके पास और एक्स है जिसमें कई वाई हैं, और आप एक ही कंपाउंड ऑब्जेक्ट के रूप में एक ही समय में एक्स और उनके वाईएस को स्टोर और पुनर्प्राप्त करना चाहते हैं, तो एक्स के लिए आपके डीएओ को वाई के लिए डीएओ भी कॉल करना चाहिए। फिर आप एक्स के लिए डीएओ में अपने ऐड() और अपडेट() विधियों में सबकुछ के आसपास एक लेनदेन डाल सकते हैं - और यहां तक ​​कि वाई डीएओ पैकेज को अपने मुख्य व्यवसाय तर्क से छिपाने के लिए निजी भी बना सकते हैं। Ie, व्यापार तर्क के बजाय:

XDAO xDAO = new XDAO(conn); 
xDAO.startTransaction(); 
boolean success = xDAO.add(x); 
if (success) 
    for (Y y : x.getYs()) { 
     success = YDAO.add(y); 
     if (!success) break; 
    } 
if (success) 
    xDAO.commit(); 
else 
    xDAO.rollback(); 

तुम बस होगा:

XDAO xDAO = new XDAO(conn); 
xDAO.add(x); 

(सफलता के साथ/प्रतिबद्ध/रोलबैक कि डीएओ को आंतरिक तर्क)

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

6

एक वेब ऐप्लिकेशन में, मैं क्या लेन-देन हदबंदी करने के लिए क्या एक भी समर्पित सूत्र में HTTP अनुरोध/प्रतिक्रिया चक्र है, जहां प्रत्येक परमाणु व्यापार आपरेशन इन चक्रों में से एक के दायरे में कार्यान्वित का लाभ लेने के, है ।

जो भी वेब ढांचा उपयोग किया जाता है (स्ट्रूट्स, जेएसएफ, जीडब्ल्यूटी, इत्यादि), आमतौर पर एक "सीम" मौजूद होता है जहां लेनदेन की कमी हो सकती है। स्ट्रूट्स में, यह आधार एक्शन क्लास हो सकता है। जीडब्ल्यूटी में, यह एक मूल RemoteServiceImpl कक्षा हो सकता है।

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

मैंने इस रणनीति को बड़े और जटिल व्यापार वेब ऐप में बड़े पैमाने पर लागू किया, और यह बहुत अच्छी तरह से काम करने के लिए साबित हुआ।

3

शायद यह उत्तर के लिए बहुत देर हो चुकी है, लेकिन विशिष्ट लेनदेन के लिए एक और कक्षा बनाने के बारे में, जो व्यापार परत और दाओ परत के बीच बैठता है? जैसे यदि किसी डीएओ से विधियों() और बी() को कुछ विशिष्ट foo() व्यवसाय विधि के लिए लेनदेन में चलाया जाना है, तो fooInTransaction() जैसे कुछ बनाएं जो लेनदेन शुरू करता है और इसमें() और b() कॉल करता है । व्यापार विधि foo() इसके लिए प्रतिनिधि।

यह व्यापार कोड को साफ रखेगा और पुन: फैक्टरिंग से डुप्लिकेशन से बचा जा सकता है।

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