2014-08-27 7 views
7

नियंत्रक तर्क:कैसे जेपीए साथ StaleObjectStateException को ठीक करने और हाइबरनेट को

def updateObject() { 

    Object o = Object.get(params.id as Long) 

    o.otherObjects.clear() 

    objectDataService.saveObject(o.id) 

    OtherObject newObject = new OtherObject; 

    o.addToOtherObjects(newObject) 

    objectDataService.saveObject(o.id) 

} 

ServiceLogic

def saveObject(long profileId) { 
    o.save(flush:true) 
} 

क्या मामलों यह सिर्फ काम करेंगे के 90% में

होता है।

समस्याओं

ERROR errors.GrailsExceptionResolver - StaleObjectStateException occurred when processing request: [GET] /controller/updateObject - parameters: 
stuff[]: data 
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]. 
Stacktrace follows: 
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1] 

मैं संबंधित प्रश्नों के माध्यम से पढ़ सकते हैं और merge कॉल ऊपर दिखने वाला मिल गया है। इसने लगभग 50% मामलों को हल किया लेकिन सभी नहीं।

+0

यदि आप इस तर्क को सेवा विधि में ले गए हैं तो क्या आप यहां बेहतर नहीं होंगे, तो यह सब एक ही लेनदेन के तहत किया गया था? –

+0

मैं सेवा अधिभारित नहीं करना चाहता हूं। क्या आपको लगता है कि यह समझ में आता है? –

+0

व्यापार तर्क को सेवाओं में स्थानांतरित करना और जितना संभव हो उतना पतला बनाना जितना संभव है (पतली से मेरा मतलब कोड की कम पंक्तियों के साथ है)। यह आपको आवश्यकतानुसार कोड का पुन: उपयोग करने में मदद करेगा और परीक्षण में भी बहुत समय बचाएगा। –

उत्तर

2

हमारे लिए कुछ अलग दृष्टिकोण अंत में नियमित रूप से उत्पन्न से StaleObjectException हल:

object = object.refresh() 

पुन: प्राप्त करने के लिए उन्हें हमारे StaleObjectExceptions का सबसे हल के बाद वस्तुओं ताज़ा। खासकर उन मामलों में जहां एक संभावना थी कि किसी ने किसी अन्य वस्तु से कहीं और काम किया होगा और इसके कुछ सदस्यों को बदल दिया होगा (अधिकांश समस्याएं संग्रह सदस्यों के साथ आती हैं)।

कुल मिलाकर परियोजना स्थिरता:

wrongly linked resources 

हम किसी विशिष्ट संसाधन फ़ाइल हम वास्तव में जरूरत नहीं थी पर एक 404 थी और इसलिए कुछ समय के लिए यह नजरअंदाज कर दिया। यह पता चला है कि लापता फाइल सत्र को खोलने का कारण बनती है - इस प्रकार StaleObjects को बाएं और दाएं बनाते हैं।

इसलिए हमेशा की तरह से अधिक का सामना करना पड़ किसी को एक संकेत के रूप में (कुछ StaleObjects हमेशा हो सकता है - जवाब ऊपर देखें) StaleObjectExceptions: सुनिश्चित करें कि सभी संसाधनों को सही ढंग से जुड़े हुए हैं और साथ ही अपना डेवलपर उपकरण (क्रोम F12) नहीं है किसी भी लापता फाइलों की रिपोर्ट करें।

4

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

आपके मामले में एक अतिरिक्त कॉल, जेपीए सीमाओं के बाहर, जो इस समस्या की सुविधा हो सकती है:

Object o = PObject.lock(profileId) 

प्रत्येक लेनदेन धागा बाध्य है और यह एक सत्र के अंदर होता है, तो दो प्रतिस्पर्धी धागे रखेंगे एक ही इकाई आईडी के लिए दो ऑब्जेक्ट संदर्भ। आशावादी लॉकिंग लक्ष्य किसी अन्य स्पष्ट लॉकिंग तंत्र के बिना प्रभावी ढंग से काम करता है।

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

इस परिदृश्य में, एक pessimistic lock बेहतर परिणाम देंगे, क्योंकि यह के रूप में करने का विरोध किया optimistic fail-fast approach इंतजार कर शामिल है।

+0

मैंने अपना कोड अपडेट किया। .lock() कॉल अब और नहीं है। मेरे पास अभी भी कॉल के लगभग 20% बार मौका है। यह समवर्ती नहीं है (मैं इसे एकल उपयोगकर्ता के रूप में अकेला बना रहा हूं, इसलिए कोई समवर्ती संपादन नहीं) –

5

StaleObjectStateException:

जैसा कि पहले ही इस अपवाद के बारे में टिप्पणी की। जब एक अमान्य संस्करण-एड डोमेन ऑब्जेक्ट फ़्लश (स्पष्ट या निहित) के दौरान सत्र में होता है तो संस्करण संख्या बंप हो जाती है लेकिन यह डेटाबेस तक जारी नहीं है। फिर, जब यह फिर से वैध हो जाता है और सहेजा जाता है और फ़्लश हो जाता है, तो हाइबरनेट इसे बाध्य मानता है, क्योंकि संस्करण संख्या डेटाबेस में संस्करण से मेल नहीं खाती है और यह StaleObjectStateException फेंकता है।

यह हल हो सकता है।

  1. आप अगर यह 1 तब है जब आप प्रोग्राम का उपयोग करके अपडेट करना पड़ता है अद्यतन करने से पहले संस्करण मूल्य पता लगाने के लिए है। अद्यतन के विशेष संचालन पर।
  2. @version एनोटेशन का उपयोग करके।

@version के बारे में:

आशावादी लॉकिंग के लिए संस्करण संख्या तंत्र एक @version एनोटेशन के माध्यम से प्रदान की जाती है। उदाहरण: @version एनोटेशन

@Entity 
public class Flight implements Serializable { 
... 
    @Version 
    @Column(name="OPTLOCK") 
    public Integer getVersion() { ... } 
} 

यहाँ, संस्करण संपत्ति OPTLOCK स्तंभ के लिए मैप किया गया है, और इकाई प्रबंधक इसे इस्तेमाल करता है परस्पर विरोधी अपडेट पता लगाने के लिए, और रोकने कि द्वारा ओवरराइट किया जाएगा अद्यतन की हानि एक अंतिम-प्रतिबद्ध-जीत रणनीति @version

Grails पर अधिक जानकारी के लिए नीचे दिए गए लिंक का संदर्भ लें, इसमें गिट हब कोड है।
test for GRAILS-8937: HibernateOptimisticLockingFailureException

+0

क्या आप अपने समाधानों पर विस्तार कर सकते हैं? मैं @version एनोटेशन का उपयोग कैसे करूं और मैं पहले समाधान में क्या अपडेट करूं? –

+1

@ सेबेस्टियनफ्लुकीगर: वे अपवाद को हल करने के लिए दृष्टिकोण हैं, संस्करण उपयोग को समझने के लिए हाइबरनेट फ्रेमवर्क के बारे में अधिक जानकारी देखें। मैंने संस्करण के बारे में कुछ विवरण भी अपडेट किए हैं। अन्य दिया गया लिंक ग्राइल्स से संबंधित समाधान पर बताता है। संस्करण संख्या पढ़ने के लिए समाधान। तालिका से और उसके बाद कोड लिखकर उस संस्करण को अद्यतन करें। – Rudra

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