2012-03-29 36 views
14

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

abstract class AbstractService { 

    public void process() { 
     // Do common initialisation code here 
     processSpecific(); 
     // Do common completion code here 
    } 

    abstract protected void processSpecific(); 
} 


@Service @Transactional 
public class FirstSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do specific processing code here 
    } 
} 


@Service @Transactional 
public class SecondSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do different specific processing code here 
    } 
} 

प्रत्येक ठोस उप श्रेणी सेवा में विशिष्ट कोड डेटाबेस में परिवर्तन है, जो लेन-देन संबंधी प्रचार के रूप में REQUIRED है बनाने के लिए डीएओ परत करने के लिए कई कॉल करता है प्रकार।

अब उपरोक्त परिभाषित सेवाओं के साथ, मैंने पाया कि इन ठोस उप-वर्ग सेवाओं के किसी भी कोड के अंदर कोई मौजूदा लेनदेन नहीं था, और डीएओ परत के लिए प्रत्येक कॉल एक नया लेनदेन बना रहा था, बदलाव कर रहा था, लेनदेन और वापसी कर रहा है।

हालांकि, अगर मैं @Transactional साथ सार सुपर स्तरीय व्याख्या करते हैं, तो एक सौदे ठीक से बनाई गई है, और डीएओ परत को उप-कॉल सभी मौजूदा लेनदेन में भाग लेते हैं।

तो मेरा सवाल यह है कि @Transactional व्यवहार विरासत के लिए नियम क्या हैं? कंक्रीट उप-वर्ग सेवाओं पर वसंत @Transactional का उपयोग क्यों नहीं करता है, जो वास्तव में तत्काल है? क्या @Transactional इस मामले में सुपर-क्लास पर होना चाहिए क्योंकि वह जगह है जहां सार्वजनिक प्रविष्टि-बिंदु विधि है?

+0

वैसे, मैंने [प्रासंगिक स्प्रिंगसोर्स प्रलेखन] (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework पर एक नज़र डाली है -reference.html # लेन-देन-घोषणात्मक-टिप्पणियां), लेकिन ऐसा लगता है कि यह कवर नहीं होता है। – DuncanKinnear

उत्तर

9

वसंत लेनदेन प्रलेखन से,

नोट: प्रॉक्सी मोड (जो डिफ़ॉल्ट है), केवल 'बाह्य' विधि प्रॉक्सी के माध्यम से आने वाले कॉल बीच में रोका जा होगा। इसका अर्थ यह है कि 'स्वयं-आमंत्रण', यानी लक्षित ऑब्जेक्ट के भीतर कुछ कॉल करने वाले लक्ष्य ऑब्जेक्ट के भीतर एक विधि, वास्तविक लेनदेन को रनटाइम पर नहीं ले जाएगी, भले ही चालित विधि @ ट्रान्सएक्शनल के साथ चिह्नित हो!

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

बुनाई में देखें।

+0

लेकिन क्या प्रॉक्सी 'फर्स्ट स्पेसिफिक सर्विस' का उदाहरण नहीं होगा? इस मामले में, सिस्टम उस उदाहरण की बाहरी 'प्रक्रिया' विधि को बुलाएगा, और उदाहरण स्वयं को '@ लेनदेन' के रूप में चिह्नित किया जाएगा। मैं पूरी तरह से समझता हूं कि आंतरिक निजी या संरक्षित विधियां जिन्हें 'ट्रांजेक्शनल' के रूप में चिह्नित किया गया है, लेनदेन को प्रभावित नहीं करेंगे, लेकिन मेरे पास यह नहीं है। मेरा पूरा बीन '@ लेनदेन 'के रूप में चिह्नित है। – DuncanKinnear

+0

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

+0

कैब आप उपरोक्त मेरे उदाहरण के संबंध में 'भार समय बुनाई' समझाते हैं। यह इन (प्रदूषित) उदाहरण सेवाओं का कोड कैसे बदल सकता है? – DuncanKinnear

1

क्या आपने transaction propagation के बारे में हिस्सा पढ़ा है और इसे @Transactional का उपयोग करके कॉन्फ़िगर किया जा सकता है?

ब्याज का एक अन्य क्षेत्र स्प्रिंग सिफारिश की है कि है कि आप annotate concrete classes (विरोध करता है के रूप में इंटरफेस टिप्पणी करने के लिए) चाहिए।

+0

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

+1

यदि आप यह सुनिश्चित करना चाहते हैं कि आपके डीएओ हमेशा एक मौजूदा लेनदेन (आपकी सेवा द्वारा शुरू की गई) में भाग लेते हैं तो आपको डीएओ को @ ट्रांस्सेक्शनल (प्रचार = [प्रचार .MANDATORY] (http://static.springsource.org) को कॉन्फ़िगर करना चाहिए। /spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/Propagation.html#MANDATORY)), क्योंकि [REQUIRED] का उपयोग करना (http://static.springsource.org/spring/docs/3.1 .x/javadoc-api/org/springframework/लेनदेन/एनोटेशन/Propagation.html # आवश्यक) कोई नया लेनदेन नहीं करेगा यदि कोई मौजूद नहीं है। – matsev

+0

हां, यह भविष्य में इन मुद्दों को पकड़ने का एक तरीका होगा, लेकिन यह अभी भी यह नहीं बताता कि विरासत के नियम क्या हैं। – DuncanKinnear