@ ट्रान्सएक्टेंशियल एनोटेशन कहाँ से संबंधित है?


528

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

जवाबों:


537

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


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

5
क्या वैश्विक लेन-देन इनमें से एक से अधिक हो सकता है @ ट्रान्सैटेक्शनल (प्रचार = प्रसार। आवश्यक)? या @ लेन-देन हमेशा एक लेनदेन के लिए एक सीमा है? मुझे यकीन नहीं है कि मैं इसे दस्तावेज़ीकरण से मिला हूं, लेकिन यह थोड़ा सा लगता है कि आप लेनदेन भी बना सकते हैं जिसमें
@ ट्रान्सएक्टेंशनल

1
हां, मुझे लगता है कि सबसे बाहरी @ ट्रान्सैटेक्शनल वह है जो लेन-देन के लिए सीमा बन जाती है अगर Propagation.REQUIRED चालू हो।
duffymo


309

सामान्य तौर पर मैं दूसरों से यह कहते हुए सहमत होता हूं कि लेनदेन आमतौर पर सेवा स्तर पर शुरू किए जाते हैं (यह इस बात पर निर्भर करता है कि आपको किस प्रकार की आवश्यकता है)।

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

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


3
क्या यह डाओ (इंटरफेस) परत में किया जाना चाहिए, डाओ इम्प्लांट में। परत या दोनों?
जोहान

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

10
@ जोहान स्प्रिंग इंटरफेस के बजाय कार्यान्वयन वर्ग पर लेनदेन एनोटेशन लगाने की सलाह देते हैं।
मथियास जी।

मैं वास्तव में इस विचार को पसंद कर रहा हूं, मेरी परियोजनाओं के लिए भी कोशिश कर रहा हूं
थॉमस आइंवलर

1
Lemme देखें कि क्या मुझे समझ में आ रहा है ... क्या आप कह रहे हैं कि मुझे @Transactionalसेवा कार्यान्वयन वर्ग में रखना चाहिए, और मुझे @Transactional(propagation = MANDATORY)DAO (रिपॉजिटरी) वर्ग के कार्यान्वयन पर रखना चाहिए ?
जॉन हेन्केल

93

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

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

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

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

ये इस तरह के प्रश्न हैं जो आपको यह तय करने की आवश्यकता है कि यह कहां रखा जाए @Transactional


41

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

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

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


38

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

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

DAO पर एनोटेटिंग लेनदेन को यथासंभव कम रखेगा, इस कमी के साथ कि आपकी सेवा परत की कार्यक्षमता एक एकल (रोलबैक योग्य) लेनदेन में नहीं होगी।

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


31

मैं परत @Transactionalपर @Serviceरखता हूं और rollbackForकिसी भी अपवाद को निर्धारित करता हूं औरreadOnly लेनदेन को आगे बढ़ाता ।

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

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

चेक किए गए बनाम अनियोजित अपवाद देखें ।


17

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


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

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

4
यदि आप उपयोग करते हैं तो नेस्टेड लेनदेन हो सकता है propagation=Propagation.REQUIRES_NEW। अन्यथा ज्यादातर मामलों के लिए, जिनमें प्रचार = अनिवार्य शामिल है, DAO सिर्फ सेवा स्तर द्वारा शुरू किए गए मौजूदा लेनदेन में भाग लेगा।
डेन कार्टर


15

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

ज्यादातर मैंने @TransactionalDAO का सिर्फ मेथड लेवल पर उपयोग किया है, इसलिए कॉन्फ़िगरेशन विशेष रूप से एक मेथड के लिए हो सकता है / डिफ़ॉल्ट (आवश्यक) का उपयोग कर

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

  2. DAO के तरीके जो इन्सर्ट / अपडेट करते हैं, मिलेंगे @Transactional

Transctional पर बहुत अच्छा ब्लॉग

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

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

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

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

6
+1 बहुत अच्छा लेख इसके बारे TransactionalमेंJava
ओक

11

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

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


10

@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से सेवा अंत बिंदु के साथ कनेक्शन बंद किए बिना एकल लेनदेन में कई कॉल कर सकते हैं।


2
बहुत जानकारीपूर्ण, धन्यवाद! बस मैं क्या देख रहा था, @Transactionalवास्तव में क्या है का एक
स्पष्टीकरण

6

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


5

यहाँ छवि विवरण दर्ज करें

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

// 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


5

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

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

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

जीथब प्रोजेक्ट- जावा-अल्गोस


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

4

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

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

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

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


3

DAO और सर्विस लेयर के बीच एक अलग मध्य परत में @Transactional रखना बेहतर है । चूंकि, रोलबैक बहुत महत्वपूर्ण है, आप अपने सभी DB हेरफेर को मध्य परत में रख सकते हैं और सर्विस लेयर में व्यावसायिक तर्क लिख सकते हैं। मध्य परत आपके DAO परतों के साथ बातचीत करेगी।

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

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

तो एक मध्य @ ट्रान्सनेशन लेयर होने से आपके कोड को बेहतर और आसान बनाने में मदद मिलेगी। अन्यथा, यदि आप DAO परत में उपयोग करते हैं, तो आप सभी कार्यों को रोलबैक करने में सक्षम नहीं हो सकते हैं। यदि आप सर्विस लेयर में उपयोग करते हैं, तो आपको कुछ मामलों में AOP (Aspect Oriented Programming) का उपयोग करना पड़ सकता है ।


2

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



1

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

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