2009-07-03 16 views
423

क्या आपको DAO कक्षाओं और/या उनके तरीकों में रखना चाहिए या डीएओ वस्तुओं का उपयोग कर कॉलिंग सेवा कक्षाओं को एनोटेट करना बेहतर है? या क्या यह "परतों" दोनों को एनोटेट करने के लिए समझ में आता है?@ ट्रांसेक्शन एनोटेशन कहां से संबंधित है?

उत्तर

438

मुझे लगता है कि लेनदेन सेवा परत पर हैं। यह वह है जो काम की इकाइयों और मामलों का उपयोग करने के बारे में जानता है। यह सही जवाब है यदि आपके पास ऐसी सेवा में इंजेक्शन देने वाले कई डीएओ हैं जिन्हें एक ही लेनदेन में एक साथ काम करने की आवश्यकता है।

+0

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

+3

क्या वैश्विक लेन-देन में इनमें से एक से अधिक @ ट्रान्सएक्शनल (प्रचार = प्रचार। REQUIRED) शामिल हो सकता है? या @ ट्रांसेक्शन हमेशा एक लेनदेन के लिए एक सीमा है? मुझे यकीन है कि मैं प्रलेखन से समझ में आ गया नहीं कर रहा हूँ, लेकिन यह एक सा है कि आप भी लेनदेन है कि @Transactional तरीकों से मिलकर बनता है और सब कुछ है कि अंदर – lisak

+1

हाँ, मुझे लगता है कि सबसे बाहरी @Transactional एक सीमा हो जाता है चलाता है बना सकते हैं लगता है लेनदेन के लिए अगर प्रचार। REQUIRED चालू है। – duffymo

36

सामान्य मामला सेवा स्तर स्तर पर एनोटेट करना होगा, लेकिन यह वास्तव में आपकी आवश्यकताओं पर निर्भर करता है।

सेवा परत पर टिप्पणी करने से डीएओ स्तर पर एनोटेट करने से अधिक लेनदेन होंगे। लेनदेन अलगाव स्तर के आधार पर जो समस्याएं पैदा कर सकते हैं, क्योंकि समवर्ती लेन-देन उदाहरण में एक-दूसरे के परिवर्तन नहीं देख पाएंगे। दोहराने योग्य पढ़ें।

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

प्रचार मोड को डिफ़ॉल्ट रूप से सेट किया गया है, तो दोनों परतों को एनोटेट करने का अर्थ नहीं है।

73

पारस्परिक एनोटेशन को उन सभी परिचालनों के आसपास रखा जाना चाहिए जो अविभाज्य हैं।

उदाहरण के लिए, आपका कॉल "पासवर्ड बदलें" है। इसमें दो ऑपरेशंस

  1. पासवर्ड बदलें।
  2. परिवर्तन का ऑडिट करें।
  3. ग्राहक को ईमेल करें कि पासवर्ड बदल गया है।

तो उपरोक्त में, यदि ऑडिट विफल रहता है, तो क्या पासवर्ड परिवर्तन भी असफल हो सकता है? यदि ऐसा है, तो लेनदेन लगभग 1 और 2 होना चाहिए (इसलिए सेवा परत पर)। अगर ईमेल विफल रहता है (शायद इस पर किसी प्रकार का असफल सुरक्षित होना चाहिए तो यह असफल नहीं होगा) तो क्या इसे परिवर्तन पासवर्ड और ऑडिट वापस लेना चाहिए?

@Transactional कहां रखना है, यह तय करते समय आपको ऐसे प्रश्न पूछने की आवश्यकता है।

7

यह सेवा परत में पाना बेहतर है! इस लेख में से एक पर यह स्पष्ट रूप से समझाया गया है कि मैं कल आया था! यहां the link है जो आप देख सकते हैं!

37

पारंपरिक वसंत आर्किटेक्चर के लिए सही उत्तर सेवा वर्गों पर लेनदेन संबंधी अर्थशास्त्र रखना है, जिन कारणों से पहले से ही वर्णन किया गया है।

वसंत में एक उभरती हुई प्रवृत्ति domain-driven design (डीडीडी) की ओर है। Spring Roo इस प्रवृत्ति को अच्छी तरह से उदाहरण देता है। विचार सामान्य ऑब्जेक्ट POJO को richer को सामान्य वसंत आर्किटेक्चर (आमतौर पर वे anemic) पर होने की तुलना में बनाना है, और विशेष रूप से डोमेन ऑब्जेक्ट्स पर लेनदेन और दृढ़ता सेमेन्टिक्स डालना है।जिन मामलों में इसकी आवश्यकता है, सरल सीआरयूडी ऑपरेशंस है, वेब नियंत्रक सीधे डोमेन ऑब्जेक्ट पीओजेओ (वे इस संदर्भ में इकाइयों के रूप में काम कर रहे हैं) पर काम करते हैं, और कोई सेवा स्तर नहीं है। ऐसे मामलों में जहां डोमेन ऑब्जेक्ट्स के बीच कुछ प्रकार की समन्वय की आवश्यकता होती है, आप परंपरा के अनुसार @Transaction के साथ सेवा बीन हैंडल कर सकते हैं। आप REQUIRED जैसे डोमेन ऑब्जेक्ट्स पर लेनदेन प्रचार सेट कर सकते हैं ताकि डोमेन ऑब्जेक्ट्स किसी भी मौजूदा लेन-देन का उपयोग कर सकें, जैसे सेवा बीन में शुरू किए गए लेन-देन।

तकनीकी रूप से यह तकनीक AspectJ और <context:spring-configured /> का उपयोग करती है। Roo डोमेन ऑब्जेक्ट सामग्री (मूल रूप से फ़ील्ड्स और व्यावसायिक विधियों) से इकाई अर्थशास्त्र (लेनदेन और दृढ़ता) को अलग करने के लिए AspectJ अंतर-प्रकार परिभाषाओं का उपयोग करता है।

+1

अच्छा संपादन @naxa। धन्यवाद। –

12

आमतौर पर, किसी को सेवा परत पर लेनदेन करना चाहिए।

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

17

या क्या यह "परतों" दोनों को एनोटेट करने के लिए समझ में आता है? - क्या यह सेवा परत और दाओ परत दोनों को एनोटेट करने का अर्थ नहीं है - यदि कोई यह सुनिश्चित करना चाहता है कि डीएओ विधि को डीएओ में "अनिवार्य" प्रचार के साथ सेवा परत से हमेशा (प्रचारित) कहा जाता है। यह यूआई परत (या नियंत्रकों) से डीएओ विधियों के लिए कुछ प्रतिबंध प्रदान करेगा। इसके अलावा - जब यूनिट परीक्षण विशेष रूप से डीएओ परत - डीएओ एनोटेटेड होने से यह भी सुनिश्चित होगा कि यह लेनदेन संबंधी कार्यक्षमता के लिए परीक्षण किया जाता है।

+0

इस परिणाम को नेस्टेड लेनदेन में नहीं कर पाएंगे? और सभी सूक्ष्म समस्याएं जो इसके साथ जाती हैं? – HDave

+9

नहीं, जेपीए में कोई घोंसला लेनदेन नहीं है।उन्हें दोनों में रखना पूरी तरह ठीक होगा - यदि आप डीएओ को मारते समय पहले ही लेनदेन में हैं, तो वह लेनदेन जारी रहेगा। – fool4jesus

+3

यदि आप 'प्रचार = प्रचार। REQUIRES_NEW' का उपयोग करते हैं तो नेस्टेड लेनदेन हो सकता है। अन्यथा ज्यादातर मामलों के लिए, प्रक्षेपण = अनिवार्य समेत, डीएओ केवल सेवा परत द्वारा शुरू किए गए मौजूदा लेनदेन में भाग लेगा। –

252

आम तौर पर मैं दूसरों से सहमत हूं कि लेनदेन आमतौर पर सेवा स्तर पर शुरू होता है (ग्रैन्युलरिटी के आधार पर आपको निश्चित रूप से आवश्यकता होती है)।

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

मैं भी एकीकरण परीक्षण जहां मैं इस टिप्पणी के लिए सभी सेम (सेम पोस्ट प्रोसेसर) की जाँच की है और असफल अगर वहाँ एक सेम है कि सेवाओं परत से संबंधित नहीं है में अनिवार्य अलावा अन्य प्रचार के साथ एक @Transactional एनोटेशन है। इस तरह से मैं सुनिश्चित करता हूं कि हम गलत परत पर लेनदेन शुरू नहीं करते हैं।

+45

यह एक अच्छा विचार है। इच्छा है कि मैं इसे 10 बार बढ़ा सकता हूं। – HDave

+2

यह दाओ प्रत्यारोपण में दाओ (इंटरफेस) परत में किया जाना चाहिए। परत या दोनों? – Johan

+3

मुझे नहीं पता कि यह इस चर्चा में फिट बैठता है, लेकिन गैर-लेखन संचालन में दाओ प्रत्यारोपण में एक और युक्ति को @ ट्रान्सैक्शनल (readOnly = true) जोड़ दिया जा सकता है। – maxivis

12

डेटाबेस स्तर में लेन-देन के लिए

ज्यादातर मैं @Transactional डीएओ की बस पर विधि स्तर में प्रयोग किया जाता है, तो विन्यास/एक विधि के लिए विशेष रूप हो सकता है डिफ़ॉल्ट का उपयोग कर (अपेक्षित)

  1. डीएओ की विधि है कि डेटा प्राप्त fetch (select ..) - @Transactional की आवश्यकता नहीं है, इससे लेनदेन इंटरसेप्टर/और एओपी प्रॉक्सी की वजह से कुछ ओवरहेड हो सकता है जिसे के रूप में निष्पादित करने की आवश्यकता है।

  2. डीएओ के तरीकों कि सम्मिलित करना/अद्यतन @Transactional

transctional

पर बहुत अच्छा ब्लॉग मिल जाएगा अनुप्रयोग स्तर के लिए -
मैं व्यापार तर्क के लिए लेन-देन संबंधी उपयोग कर रहा हूँ मैं चाहूँगा सक्षम होने के लिए अप्रत्याशित त्रुटि

@Transactional(rollbackFor={MyApplicationException.class}) 
public void myMethod(){ 

    try {  
     //service logic here  
    } catch(Throwable e) { 

     log.error(e) 
     throw new MyApplicationException(..); 
    } 
} 
+2

+1 'जावा' में 'लेनदेन' के बारे में बहुत अच्छा लेख +1 – oak

24

स्थान पर रोलबैक @Transactional@Service परत पर और लेनदेन को अनुकूलित करने के लिए rollbackFor कोई अपवाद और readOnly सेट करें।

डिफ़ॉल्ट @Transactional तक केवल RuntimeException (अनियंत्रित अपवाद) के लिए दिखाई देगा, Exception.class (जांचे हुए अपवादों) को रोलबैक यह किसी भी अपवाद के लिए रोलबैक होगा निर्धारित करके।

@Transactional(readOnly = false, rollbackFor = Exception.class) 

Checked vs. Unchecked Exceptions देखें।

1

मैं विधि स्तर पर सेवा परत पर @Transactional का उपयोग करना पसंद करता हूं।

4

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

हम 2 मॉडल अर्थात Country और City:

इसलिए उदाहरण ले सकते हैं। Country और City मॉडल की संबंधपरक मानचित्रण एक Country कई शहरों की तरह हो सकता है तो मानचित्रण की तरह है,

@OneToMany(fetch = FetchType.LAZY, mappedBy="country") 
private Set<City> cities; 

यहाँ देश उन्हें Lazily प्राप्त करने में कठिनाई के साथ कई शहरों के लिए मैप किया। तो यहां @Transactinal की भूमिका आती है जब हम डेटाबेस से देश वस्तु पुनर्प्राप्त करते हैं तो हमें देश वस्तु के सभी डेटा मिलेंगे लेकिन शहरों का सेट नहीं मिलेगा क्योंकि हम शहरों को LAZILY ला रहे हैं।

//Without @Transactional 
public Country getCountry(){ 
    Country country = countryRepository.getCountry(); 
    //After getting Country Object connection between countryRepository and database is Closed 
} 

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

//with @Transactional 
@Transactional 
public Country getCountry(){ 
    Country country = countryRepository.getCountry(); 
    //below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal 
    Object object = country.getCities().size(); 
} 

तो मूल रूप से @Transactional सेवा अंत बिंदु के सिलसिले को बंद किए बिना एक लेन-देन में एक से अधिक कॉल कर सकते हैं।

3

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

1

@Transactional सेवा परत जो डीएओ परत (@Repository) यानी डेटा बेस संबंधित संचालन के लिए नियंत्रक परत (@Controller) और सेवा परत कॉल का उपयोग करके कहा जाता है में उपयोग करता है।

2

सबसे पहले हम परिभाषित करते हैं कि हमें लेनदेन का उपयोग करना है?

मुझे लगता है कि सही जवाब है - जब हम यकीन है कि कार्रवाई की है कि अनुक्रम एक परमाणु आपरेशन के रूप में एक साथ समाप्त हो जाएगी या कोई भी परिवर्तन भले ही क्रियाओं में से एक में विफल रहता है किया जाएगा बनाने की जरूरत है।

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

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

1

सेवा परत व्यापार तर्क यहाँ मौजूद है, यह विस्तार स्तर यूज-केस व्यवहार शामिल अधिकांश @Transactional टिप्पणियां जोड़ने के लिए सबसे अच्छी जगह है।

मान लीजिए कि हम इसे डीएओ में जोड़ते हैं और सेवा से हम 2 डीएओ कक्षाओं, एक असफल और अन्य सफलता को बुला रहे हैं, इस मामले में यदि @ ट्रान्सएक्शनल सेवा पर नहीं है तो एक डीबी प्रतिबद्ध होगा और अन्य रोलबैक होगा।

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

https://github.com/VishalTambe/java-algos/

0

enter image description here

@Transactional सेवा परत पर इस्तेमाल किया जाना चाहिए के रूप में यह व्यापार तर्क होते हैं। डीएओ परत में आमतौर पर केवल डेटाबेस सीआरयूडी ऑपरेशंस होता है।

// the service class that we want to make transactional 
@Transactional 
public class DefaultFooService implements FooService { 

    Foo getFoo(String fooName); 

    Foo getFoo(String fooName, String barName); 

    void insertFoo(Foo foo); 

    void updateFoo(Foo foo); 
} 

स्प्रिंग डॉक: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html

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