2009-10-23 17 views
33

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

मेरे आदेश सेवा परत विधियों को कॉल करते हैं जो @Transactional एनोटेशन के साथ एनोटेटेड हैं। इनमें से कुछ सेवा परत विधियां केवल पढ़ने के लिए हैं - उदा। @Transactional(readOnly=true) - और कुछ पढ़े/लिखते हैं।

मेरी सेवा परत एक कमांड हैंडलर का खुलासा करती है जो वेब परत की तरफ से पास किए गए आदेश निष्पादित करती है।

@Transactional 
public Command handle(Command cmd) throws CommandException 

मुझे लगता है मैं सही आदेश हैंडलर के handle() विधि व्यवहार बनाने में कर रहा हूँ। यह वह जगह है जहां भ्रम आता है। यदि कमांड के कार्यान्वयन से कई सर्विस लेयर विधियों को कॉल किया जाता है, तो आदेश हैंडलर को यह जानने का कोई तरीका नहीं है कि कमांड के भीतर बुलाए गए ऑपरेशन केवल पढ़ने के लिए, पढ़/लिखने या संयोजन दोनों के।

मुझे समझ में नहीं आता कि इस उदाहरण में प्रचार कैसे काम करता है। अगर मुझे handle() विधि readOnly=true बनाना था, तो क्या होता है यदि आदेश तब सेवा परत विधि को कॉल करता है जो @Transactional(realOnly=false) के साथ एनोटेट किया गया है?

मैं इस का एक बेहतर समझ की सराहना करते हैं और अपनी टिप्पणी का स्वागत करते हैं चाहता हूँ ...

एंड्रयू

+1

तो दोनों विरोधाभासी जवाब में से जो सच है? क्या किसी ने जांच करने के लिए परेशान किया है? – LuGo

+0

चूंकि 'हैंडल() '_may_ कॉल विधियां जो लिखती हैं, लेनदेन को लिखने की अनुमति देनी चाहिए। यह एक समाधान के रूप में ठीक और सही होगा। यदि आप वास्तव में चाहते थे, तो आप टेक्सास को प्रोग्रामेटिक रूप से शुरू करने और केवल पढ़ने के लिए स्विचिंग की जांच कर सकते हैं - शायद कमांड की विशेषता के माध्यम से - लेकिन मुझे गंभीरता से संदेह है कि यह प्रयास के लायक है। –

उत्तर

51

सबसे पहले, के बाद से वसंत हठ ही नहीं करता है, यह क्या readOnly वास्तव में मतलब यह होना चाहिए निर्दिष्ट नहीं कर सकते । यह विशेषता प्रदाता को केवल एक संकेत है, व्यवहार इस मामले में, हाइबरनेट पर निर्भर करता है।

आप readOnlytrue के रूप में निर्दिष्ट करते हैं, फ्लश मोड लेन-देन करने से सत्र को रोकने वर्तमान हाइबरनेट सत्र में के रूप में FlushMode.NEVER स्थापित किया जाएगा।

इसके अलावा, setReadOnly (true) जेडीबीसी कनेक्शन पर कॉल किया जाएगा, जो अंतर्निहित डेटाबेस का संकेत भी है। यदि आपका डेटाबेस इसका समर्थन करता है (संभवतः यह करता है), यह मूल रूप से FlushMode.NEVER जैसा ही प्रभाव डालता है, लेकिन यह मजबूत है क्योंकि आप मैन्युअल रूप से फ्लश भी नहीं कर सकते हैं।

अब देखते हैं कि लेनदेन प्रचार कैसे काम करता है।

यदि आप स्पष्ट रूप से readOnly से true पर सेट नहीं करते हैं, तो आप लेनदेन को पढ़/लिखेंगे। लेनदेन विशेषताओं (जैसे REQUIRES_NEW) के आधार पर, कभी-कभी आपका लेनदेन किसी बिंदु पर निलंबित कर दिया जाता है, एक नया शुरू होता है और अंततः प्रतिबद्ध होता है, और उसके बाद पहला लेनदेन फिर से शुरू हो जाता है।

ठीक है, हम लगभग वहां हैं। चलो देखते हैं कि इस परिदृश्य में readOnly क्या लाता है।

तो एक पढ़ने में एक विधि/ लेन-देन बारे में कहता है एक विधि है कि एक केवल पढ़ने के लिए लेन-देन की आवश्यकता है, पहले एक, निलंबित किया जाना चाहिए क्योंकि अन्यथा एक फ्लश/प्रतिबद्ध दूसरी विधि के अंत में क्या होगा।

इसके विपरीत, यदि आप एक केवल पढ़ने के लिए लेनदेन है कि पढ़ने/लिखने की आवश्यकता के भीतर से एक विधि कॉल, फिर से, पहले एक निलंबित कर दिया जाएगा, क्योंकि यह प्लावित नहीं किया जा सकता/प्रतिबद्ध है, और दूसरी विधि है कि जरूरत है।

में केवल पढ़ने के लिए करने के लिए केवल पढ़ने के लिए, और पढ़ने/लिखने पढ़ने/लिखने मामलों बाहरी लेन-देन की जरूरत नहीं है निलंबित किया जाना है (जब तक आप स्पष्ट रूप से अन्यथा प्रचार निर्दिष्ट करते हैं,)।

+0

क्या आप निश्चित हैं? क्या "केवल पढ़ने के लिए" वास्तव में निर्दिष्ट प्रचार नीति को ओवरराइड करेगा? मुझे संदर्भों को खोजने में कठिनाई थी लेकिन कम से कम इस पोस्ट में जोर दिया गया है: http://imranbohoran.blogspot.ch/2011/01/spring-transactions-readonly-whats-it.html –

+11

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

+7

गलत - जैसा कि @ डांकार्टर कहते हैं, ** ** पढ़ने/लिखने के लिए ** ** पढ़ा गया ** विधि केवल ** लेनदेन चुपचाप स्प्रिंग के हाइबरनेट एकीकरण के साथ प्रतिबद्ध करने में असफल हो जाएगा। चूंकि बाहरीतम TX इंटरसेप्टर केवल पढ़ने के लिए है, हाइबरनेट सत्र कभी नहीं फिसल जाता है .. और कोई SQL अद्यतन निष्पादित नहीं किया जाता है। (यह डिफ़ॉल्ट प्रचार गुणों के साथ है - आप 'REQUIRES_NEW' आज़मा सकते हैं, लेकिन अधिकांश परिदृश्यों के लिए यह सही समाधान नहीं है।) –

8

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

क्या आप आलसी लोडिंग को आलसी लोडिंग की अनुमति देने के लिए उपयोग पैटर्न में उपयोग कर सकते हैं? इस तरह आपकी हैंडल विधि को लेन-देन की आवश्यकता नहीं है।

+1

जैसा कि @ सिजिक कहते हैं, केवल पढ़ने की स्थिति ही प्रचारित होती है - चेतावनी या किसी निदान के बिना क्यों हाइबरनेट करता है प्रतिबद्ध नहीं है :( –

+0

मैं जेपीए + हाइबरनेट + वसंत का उपयोग कर रहा हूं, और ऐसे मामले में जहां एक पठनीय लेनदेन को रीडराइट लेनदेन कहा जाता है और सभी कार्यवाही रीडराइट लेनदेन में थीं, जो संस्थाएं जारी थीं लेकिन प्रतिबद्ध थीं जो गेटर्स के माध्यम से बदल दी गई थीं/सेटर्स प्रतिबद्ध नहीं हुए। काफी उलझन में। –

9

प्रचार का परीक्षण करना काफी आसान है।

बीनएस एक लेनदेन = केवल-पढ़ने के लिए बीन 1 कहता है, जो एक लुकअप करता है और लेनदेन = पढ़ने-लिखने बीन 2 को कॉल करता है जो एक नई वस्तु को बचाता है।

  • बीन 1 केवल पढ़ने-योग्य टीएक्स शुरू करता है।

31 09: 39: 44.199 [पूल-1-धागा 1] डीबग osorm.jpa.JpaTransactionManager - नाम के साथ नए लेन-देन का निर्माण [nz.co.vodafone.wcim.business.Bean1.startSomething]: PROPAGATION_REQUIRED, ISOLATION_DEFAULT, केवल पढ़ने के लिए; '

  • बीन 2 इसमें परिक्रमा करता है।

31 09: 39: 44.230 [पूल-1-धागा 1] डीबग o.s.orm.jpa.JpaTransactionManager - लेन-देन मौजूदा

कुछ भी नहीं है में भाग लेते हुए डेटाबेस के लिए प्रतिबद्ध है।

अब propagation=Propagation.REQUIRES_NEW

  • Bean1 केवल पढ़ने के लिए tx शुरू होता है जोड़ने के लिए Bean2 @Transactional एनोटेशन बदल जाते हैं।

31 09: 31: 36.418 [पूल-1-धागा 1] डीबग osorm.jpa.JpaTransactionManager - नाम के साथ नए लेन-देन का निर्माण [nz.co.vodafone.wcim.business.Bean1.startSomething]: PROPAGATION_REQUIRED, ISOLATION_DEFAULT, केवल पढ़ने के लिए; ''

  • Bean2 tx

31 09 एक नया पढ़ने-लिखने शुरू होता है: 31: 36.449 [पूल-1-धागा 1] डीबग osorm.jpa.JpaTransactionManager -, वर्तमान लेन-देन को निलंबित बनाने नाम के साथ नया लेनदेन [nz.co.vodafone.wcim.business.Bean2.createSomething]

और बीन 2 द्वारा किए गए परिवर्तन अब डेटाबेस के लिए प्रतिबद्ध हैं।

यहां उदाहरण है, वसंत-डेटा, हाइबरनेट और ऑरैकल के साथ परीक्षण किया गया है।

@Named 
public class BeanS { 

@Inject 
Bean1 bean1; 

@Scheduled(fixedRate = 20000) 
public void runSomething() { 
    bean1.startSomething(); 
} 

} 


@Named 
@Transactional(readOnly = true) 
public class Bean1 { 

Logger log = LoggerFactory.getLogger(Bean1.class); 

@Inject 
private CircuitStateRepository csr; 

@Inject 
private Bean2 bean2; 

public void startSomething() { 

    Iterable<CircuitState> s = csr.findAll(); 
    CircuitState c = s.iterator().next(); 
    log.info("GOT CIRCUIT {}", c.getCircuitId()); 
    bean2.createSomething(c.getCircuitId()); 

} 

} 


@Named 
@Transactional(readOnly = false) 
public class Bean2 { 

    @Inject 
    CircuitStateRepository csr; 

    public void createSomething(String circuitId) { 

     CircuitState c = new CircuitState(circuitId + "-New-" + new DateTime().toString("hhmmss"), new DateTime()); 

     csr.save(c); 

    } 


} 
4

यह मौजूदा सक्रिय लेन-देन के लिए सेटिंग्स की अनदेखी करने, यह केवल एक नई लेन-देन करने के लिए सेटिंग्स लागू लगते हैं:

 
org.springframework.transaction.PlatformTransactionManager 
TransactionStatus getTransaction(TransactionDefinition definition) 
         throws TransactionException 
Return a currently active transaction or create a new one, according to the specified propagation behavior. 
Note that parameters like isolation level or timeout will only be applied to new transactions, and thus be ignored when participating in active ones. 
Furthermore, not all transaction definition settings will be supported by every transaction manager: A proper transaction manager implementation should throw an exception when unsupported settings are encountered. 
An exception to the above rule is the read-only flag, which should be ignored if no explicit read-only mode is supported. Essentially, the read-only flag is just a hint for potential optimization.
संबंधित मुद्दे