2010-06-05 13 views
12

में एक लेनदेन वापस रोलिंग मैं सेवा में एक RuntimeException फेंक दिया गया है जब मैं रोलबैक करने के लिए Grail की क्षमता का उपयोग करके लेनदेन के लिए मेरी सभी सेवाओं को अद्यतन कर रहा है। मैं है, ज्यादातर मामलों में, यह कर:एक Grails सेवा

def domain = new Domain(field: field) 
if (!domain.save()) { 
    throw new RuntimeException() 
} 

फिर भी, मैं सत्यापित करने के लिए कि यह वास्तव में लेनदेन रोलबैक होगा चाहता था ... यह मेरे लिए कि क्या करने के लिए के रूप में सोच इस बिंदु यह पहले से ही किया गया है पर मिल गया .. इसके अलावा , यदि नहीं, फ्लश स्थापित करेगा: सच परिवर्तन है कि? मैं इस बात से बहुत परिचित नहीं हूं कि स्प्रिंग/हाइबरनेट इस सब कैसे करता है :)

उत्तर

15

हाँ जो ऐसा करेगा।

Grails में लेनदेन डिफ़ॉल्ट रूप से एक सेवा विधि स्तर पर संभाला जाता है। यदि विधि सामान्य रूप से वापस आती है तो लेनदेन किया जाएगा, यदि एक रनटाइम अपवाद को फेंक दिया जाता है तो लेनदेन वापस ले जाया जाएगा।

नोट करें इसका अर्थ यह भी है कि यदि आप फ्लश का उपयोग करते हैं: सर्वर विधि में ऑब्जेक्ट को सहेजते समय सही है, तो अगर आप RuntimeException फेंकते हैं तो डीबी परिवर्तन अभी भी लुढ़क जाएंगे।

उदाहरण के लिए:

class MyService { 

def fiddle(id,id2){ 
    def domain = Domain.findById(id) 

    domain.stuff = "A change" 
    domain.save(flush:true) // will cause hibernate to perform the update statements 

    def otherDomain = OtherDomain.findById(id2)  

    otherDomain.name = "Fiddled" 

    if(!otherDomain.save(flush:true)){ // will also write to the db 
    // the transaction will be roled back 
    throw new RuntimeException("Panic what the hell happened") 
    }               
} 
} 

क्या मैं 100% स्पष्ट नहीं कर रहा हूँ Grails के साथ पर अगर एक जाँच अपवाद सीधे जावा में फेंक दिया जाता है क्या होता है/वसंत दुनिया डिफ़ॉल्ट व्यवहार लेनदेन Inceptor प्रतिबद्ध करने के लिए है लेनदेन, इसके अलावा कॉन्फ़िगरेशन में ओवरराइड किया जा सकता है।

नोट: एक चेतावनी है, और यह है कि आपके डीबी को आपके द्वारा अपडेट की जा रही तालिकाओं पर लेनदेन का समर्थन करना है। हां, यह MySQL पर पोक है :)

यह Domain.withTransaction विधि पर भी लागू होता है।

+0

बहुत बढ़िया, धन्यवाद! – RyanLynch

+0

सेवा होने के लिए खुश –

+0

RuntimeException का विस्तार करने वाले कस्टम अपवाद ठीक होना चाहिए, है ना? इसके अलावा, आप सेटिंग द्वारा MySQL में लेनदेन सक्षम कर सकते हैं: dialect = org.hibernate.dialect।डेटा स्रोत में MySQLInnoDBDialect :) – RyanLynch

2

बस स्वीकृत उत्तर में अतिरिक्त टिप्पणियां जोड़ना चाहता था, और यह एक टिप्पणी में फिट होने में बहुत लंबा था।

क्या मैं Grails के साथ पर 100% स्पष्ट नहीं कर रहा हूँ एक जाँच अपवाद फेंक दिया है

डिफ़ॉल्ट रूप से, अपवाद नहीं जाँच की जानी चाहिए, या लेन-देन लुढ़का नहीं किया जाएगा क्या होता है वापस। जाहिर है कि यह एक वसंत चीज है।

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

जागरूक रहें, हालांकि, @Transactional के साथ किसी सेवा में किसी एक विधि को चिह्नित करने से लेनदेन के साथ अपने अन्य तरीकों के स्वचालित रैपिंग को अक्षम किया जाता है। इसलिए, यदि आप इसे एक के लिए करते हैं, तो आपको उन सभी के लिए यह करना होगा। सुनिश्चित करें कि आप वास्तव में को उन चेक अपवादों को घोषित करने के लिए की आवश्यकता है;)

आप http://docs.grails.org/latest/guide/services.html पर इसके बारे में अधिक पढ़ सकते हैं।