2010-04-02 16 views
13

हाइबरनेट संदर्भ में, यह कई बार है किहाइबरनेट सत्र कैसे तोड़ें?

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

हमारे विरासत ऐप्स में से एक फ़ाइलों को डीबी तालिका में फ़ाइलों से कई रिकॉर्ड अपडेट/डालने के लिए एक सत्र का उपयोग करता है। प्रत्येक रिकॉर्ड अपडेट/डालने को एक अलग लेनदेन में किया जाता है, जिसे तब किया जाता है (या किसी त्रुटि के मामले में वापस लुढ़काया जाता है)। फिर अगले रिकॉर्ड के लिए एक नया लेनदेन खोला जाता है, और इसी तरह। लेकिन पूरे सत्र में एक ही सत्र का उपयोग किया जाता है, भले ही HibernateException प्रसंस्करण के बीच में पकड़ा गया हो। हम जेबॉस 4.2 पर हाइबरनेट 3.24.sp1 के साथ ओरेकल 9i बीटीडब्ल्यू का उपयोग कर रहे हैं।

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

हालांकि, हमें पूरे ऐप का परीक्षण करते समय सत्र विफलता को पुन: पेश करने का कोई तरीका नहीं मिला (क्या यह एक तनाव परीक्षण बीटीडब्ल्यू होगा, या ...?)। हमने डीबी के श्रोता को बंद करने के बारे में सोचा लेकिन हमें एहसास हुआ कि ऐप डीबी के लिए कनेक्शन का एक गुच्छा रख रहा है, और श्रोता उन कनेक्शनों को प्रभावित नहीं करेगा। (यह एक वेब ऐप है, जो प्रत्येक रात एक शेड्यूलर द्वारा सक्रिय किया जाता है, लेकिन इसे ब्राउज़र के माध्यम से भी सक्रिय किया जा सकता है।) फिर हमने डीबी में उन कनेक्शनों को मारने की कोशिश की, जबकि ऐप अपडेट प्रोसेस कर रहा था - इसके परिणामस्वरूप कुछ विफल अपडेट, लेकिन फिर ऐप खुशी से बाकी रिकॉर्ड अपडेट करना जारी रखा। स्पष्ट रूप से हाइबरनेट पूरे सत्र को तोड़ने के बिना हुड के नीचे टूटे हुए कनेक्शन को फिर से खोलने के लिए पर्याप्त चालाक है।

तो यह सब के बाद एक महत्वपूर्ण मुद्दा नहीं हो सकता है, क्योंकि हमारा ऐप अपने मूल रूप में भी मजबूत मजबूत प्रतीत होता है। हालांकि, यह मुद्दा मुझे परेशान करता रहता है।

  1. क्या परिस्थितियों में हाइबरनेट सत्र वास्तव में व्यर्थ हो जाता है के बाद एक HibernateException फेंक दिया गया था: मैं जानना चाहूंगा (अद्यतन: और क्या लक्षण हैं)?
  2. किसी परीक्षण में इसे पुन: पेश करने के लिए कैसे करें (अद्यतन: प्राथमिक रूप से इकाई परीक्षण के बजाय एकीकरण में)?
  3. (जैसे कि एक परीक्षण के लिए उचित शब्द क्या है?)

उत्तर

4

क्या परिस्थितियों में हाइबरनेट सत्र वास्तव में व्यर्थ हो जाता है के बाद एक HibernateException फेंक दिया गया था?

दिलचस्प सवाल। मुझे पूरा यकीन है कि मैंने ऐसे मामलों को देखा है जहां सत्र अभी भी इस तरह के अपवाद के बाद "काम कर रहा था"। समस्या यह हो सकती है कि इसकी गारंटी नहीं है। मुझे इसे और अधिक खोदने की आवश्यकता होगी।

अद्यतन: हाइबरनेट मंचों में एक हाइबरनेट डेवलपर की ओर से this message का हवाला देते हुए:

हाइबरनेट सत्र फेंक दिया जाना चाहिए जब किसी भी अपवाद तब होता है।इसे डेटाबेस के सापेक्ष एक असंगत स्थिति में छोड़ा जा सकता है। यह केवल पढ़ने के सत्र के मामले में नहीं है क्योंकि यह किसी सत्र स्तर कैशिंग को नियोजित नहीं करता है। वैकल्पिक रूप से, जब आप अपवाद होता है तो आप सत्र स्तर कैश को साफ़ कर सकते हैं (लेकिन मुझे व्यक्तिगत रूप से इस दृष्टिकोण को पसंद नहीं है क्योंकि यह एक साफ समाधान नहीं है और इसके परिणामस्वरूप भविष्य के मुद्दों और समस्याएं हो सकती हैं)।

तो समस्या वास्तव में नहीं है यदि Session "तकनीकी रूप से प्रयोग योग्य" है या नहीं, समस्या यह है कि यह अपेक्षा के अनुसार व्यवहार नहीं कर सकता है। और आप स्पष्ट रूप से यह नहीं चाहते हैं।

परीक्षण में इसे पुन: पेश कैसे करें?

आप एक ConstraintViolationException प्राप्त करने के लिए एक अखंडता बाधा का उल्लंघन करके एक शर्त एक उपवर्ग के कारण, फेंक दिया करने के लिए उदाहरण के लिए जानबूझ कर उल्लंघन हो सकता है। इस तरह के बारे में कुछ:

Session session = HibernateUtil.getCurrentSession(); 

try { 
    session.beginTransaction();  
    // execute some code that violates a unique constraint 
    ... 
    session.getTransaction().commit(); 
} catch (HibernateException e) { 
    session.getTransaction().rollback(); 
} 

// keep using the session 
try { 
    session.beginTransaction();  
    ... 
    session.getTransaction().commit(); 
} catch (HibernateException e) { 
    session.getTransaction().rollback(); 
} 
// do we reach this point? 

लेकिन मुझे यकीन नहीं है कि यह कुछ साबित होगा। मेरा मतलब है, अगर सत्र अभी भी काम कर रहा है, तो हम केवल इस विशेष मामले के लिए निष्कर्ष निकाल सकते हैं।

अद्यतन: मेरा सुझाव भूल जाओ, यह कुछ साबित नहीं करेगा। और वास्तव में, मुझे लगता है कि HibernateException के बाद यह साबित करने के लिए चीजें काम कर रही हैं (और यह अभी भी "दुर्घटना" हो सकती है) यह बेहद जटिल (तकनीकी और कार्यात्मक रूप से) होगी। तो, कुछ भी साबित करने की कोशिश करने के बजाय, मुझे लगता है कि करने के लिए सही काम सिफारिश (या सुझाए गए विकल्प का पालन करना है, लेकिन मैं सिर्फ एक नए Session और close प्रत्येक लेनदेन के लिए, अपवाद फेंक दिया या नहीं) का अनुरोध करता हूं।

ऐसे परीक्षण के लिए उचित शब्द क्या है?

एकीकरण परीक्षण? मजबूती परीक्षण?

1

इस पर मेरे विचार है कि

  1. It't अगले जानना चाहते हैं कि हाइबरनेट काम करेंगे असंभव करने के लिए, यह एक अप्रत्याशित स्थिति का सामना करना पड़ा है और अब एक अपरिभाषित राज्य में चल रहा है - मूल रूप से आप लागू हो जाएगा यूबी सत्र पर और अधिक संचालन करके।

  2. आइडिया - एक इंटरसेप्टर रजिस्टर और उस में एक HibernateException फेंक - उम्मीद है कि हाइबरनेट इसे पकड़ नहीं होगा: डी

  3. फॉल्ट इंजेक्शन?

+0

1 के संबंध में), यह मेरी समझ भी है - इसलिए मुझे खुशी है कि मैंने अपना ऐप अधिक मजबूत बना दिया। सीधी समस्या यह है कि इसे एक स्वतंत्र परीक्षण में कैसे सत्यापित किया जाए? 2) दिलचस्प लगता है, क्योंकि यह ऐप को संशोधित किए बिना किया जा सकता है। –

3

दिलचस्प एक। बताने का सबसे अच्छा तरीका है कि हाइबरनेट के स्रोतों पर नज़र डालें।जहां तक ​​मैं समझ गया, Session चारों ओर ज्यादा राज्य ले नहीं करता है, निम्नलिखित सामान के अलावा:

  • प्रथम स्तर कैश (StatefulPersistenceContext देखें) - यह वास्तव में इस लेनदेन की विफलता के बाद तोड़ा जा सकता है,
  • क्रिया कतार (देखें ActionQueue) - यदि आप मैन्युअल फ्लशिंग करते हैं तो ठीक है प्रतीत होता है;
  • घटना श्रोताओं - उनके उदाहरणों सत्र के बारे में पता कर रहे हैं (EventSource देखें) और, जैसा कि आप ध्यान दिया होगा, JDBC अपवाद हमेशा फ्लशिंग (DefaultFlushEventListener, और अधिक सटीक होना करने के लिए), लेकिन AbstractFlushingEventListener पर एक नज़र के कारण होता है दिखाता है कि वे वास्तव में सत्र के JDBCContext और ActionQueue के साथ काम करते हैं।

और आखिरी बात यह है कि लेनदेन का रोलबैक किसी भी तरह से सत्र स्थिति में हस्तक्षेप नहीं करता है, JDBCTransaction देखें।

इसलिए जहां तक ​​मैंने खेला है, Session वास्तव में एक दोषपूर्ण लेनदेन से बचता है, सिवाय इसके कि पहले स्तर के कैश थोड़ा गलत हो सकता है; इसके आस-पास पहुंचने के लिए आप राज्यों को स्पष्ट रूप से पुन: सिंक्रनाइज़ करने के लिए session.refresh या session.load पर कॉल करना पसंद कर सकते हैं।

संपादित करें: JDBC अपवाद परीक्षण करने के लिए तेज तरीका शायद session.createSQLQuery("something offensive to SQL parser").executeUpdate() है - आप एक आदर्श SQLGrammarException मिल जाएगा - और एक टूटी हुई लेनदेन =)

0

परीक्षण के लिए सत्र का एक उपवर्ग बनाएँ। कुछ विशिष्ट परिदृश्य में अपवाद फेंकने के लिए इसे कार्यान्वित करें। एक परीक्षण विशिष्ट हाइबरनेट कॉन्फ़िगरेशन का उपयोग करें जो आपके परीक्षण सत्र का उपयोग करने के लिए हाइबरनेट सेट करता है।

+0

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

+0

शायद मुझे समझ में नहीं आता कि आप क्या खोज रहे हैं। आप एक टूटे हुए (उदा। अनिर्धारित) राज्य में हाइबरनेट डालने के लिए एक विश्वसनीय तरीका ढूंढ रहे हैं? और फिर क्या? – james

+0

मैं हाइबरनेट सत्र को एक टूटी हुई स्थिति में रखने का एक विश्वसनीय तरीका ढूंढ रहा हूं, ताकि हमारे ऐप का पुराना संस्करण (जो लेनदेन में एक ही सत्र का पुन: उपयोग करता है) विफल हो जाता है, और नया संस्करण (जो प्रत्येक लेनदेन के लिए एक नया सत्र प्राप्त करता है)) परीक्षा पास करता है। –

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