2011-11-14 9 views
26

यह एक डिज़ाइन प्रश्न है, कंक्रीट कोड मेरे नीचे की रक्षा के लिए सबमिट नहीं किया गया है।org.hibernate.Session.clear() हानिकारक माना जाता है?

  1. खुला सत्र
  2. प्रारंभ लेन-देन
  3. व्यापार (पढ़ सकते हैं और डेटा को संशोधित)
  4. लेन-देन
  5. बंद सत्र कमिट कार्य करें:

    जब हाइबरनेट के साथ काम कर के रूप में इस मानक कार्यप्रवाह है

संभवतः संभवतः 2-4 के माध्यम से पुनरावृत्तियों।

सत्र.क्लियर() के लिए उचित उपयोग के मामले क्या हैं?

ए: मेरे पास ठोस समस्या है जो कोड का एक (बड़ा) टुकड़ा है जो इकाइयों को लोड और संशोधित करता है, फिर सत्र को स्पष्ट करता है, अनिवार्य रूप से किए गए परिवर्तनों को फेंक देता है। (पूरा करने के लिए व्यवसाय कार्य में इकाइयों को संशोधित करना शामिल नहीं है, इसलिए कोड "काम करता है")।

मुझे लगता है कि सही डिजाइन यह सुनिश्चित करना होगा कि कोड का (बड़ा) टुकड़ा परिवर्तन नहीं करता है जो इसे सहेजना नहीं चाहता है?

बी: मुझे लगता है कि सत्र। स्क्वायर() सुविधा/लचीलापन के लिए मौजूद है, न कि क्योंकि इसका उपयोग करना एक अच्छा विचार है।

क्या मैंने हाइबरनेट दर्शन को गलत समझा है?

सी: सबक्वेस्टियन: क्या कार्य पूर्ण होने के लिए फ्रेमवर्क कोड के लिए यह एक बुरा विचार है() सत्र पूरा होने पर सत्र? आईएमएचओ, जब कार्य पूरा हो जाता है तो सत्र गंदा हो जाता है, तो ढांचे को शिकायत करनी चाहिए! सत्र बंद होना चाहिए, क्योंकि कार्य पूरा हो रहा है ... (मिनट के लिए प्रदर्शन को रद्द करना)

(लेबल ए, बी और सी ताकि आप इंगित कर सकें कि आप किस भाग का जवाब दे रहे हैं)।

उत्तर

29

विज्ञापन। एक: ऐसा लगता है कि आप जानते हैं कि clear() क्या करता है। इसे स्पष्ट रूप से कॉल करने का कारण एल 1 कैश से सभी प्रबंधित इकाइयों को हटाना है, ताकि एक लेनदेन में बड़े डेटा सेट को संसाधित करते समय यह असीम रूप से बढ़े न हो।

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

आप stateless sessions का भी उपयोग कर सकते हैं।

विज्ञापन। बी: नहीं, यह उपर्युक्त कारणों से मौजूद है: यह सुनिश्चित करने के लिए कि एल 1 (सत्र कैश) बहुत अधिक नहीं बढ़ता है। बेशक इसे मैन्युअल रूप से बनाए रखना एक खराब विचार है और एक संकेत है कि बड़े डेटा सेट के लिए एक और उपकरण का उपयोग किया जाना चाहिए, लेकिन कभी-कभी यह जरूरी है।

ध्यान दें कि जेपीए विनिर्देश में clear() और flush() विधि भी है।इस मामले में आपको clear() पर कॉल करने से पहले डेटाबेस (स्पष्ट अपडेट) में परिवर्तनों को धक्का देने के लिए पहले flush() पर कॉल करना चाहिए।

विज्ञापन। सी: वास्तव में उपयोगकर्ता को चेतावनी देना एक अच्छा विचार है (शायद अपवाद फेंकने के बजाय चेतावनी संदेश जारी करके) जब वह गंदे परिवर्तनों के साथ सत्र को साफ़ करता है। मुझे यह भी नहीं लगता कि ढांचा कोड को clear() बिना शर्त के कॉल करना चाहिए, जब तक कि यह सुनिश्चित न हो कि उपयोगकर्ता कोड यह फ्लश चलाता है या कोई बदलाव नहीं करता है।

+0

विज्ञापन ए): एक लेनदेन में बड़े डेटासेट को प्रोसेस करना मेरे लिए खराब डिज़ाइन जैसा लगता है (दिया गया है, मैंने शायद सभी संभावित समस्याओं का विचार नहीं किया हो सकता है ...)। एक इकाई को "स्पष्ट रूप से" बनाए रखने का क्या मतलब है? session.save (संस्था)? विज्ञापन सी): लगता है जैसे हम मानते हैं कि ढांचे को ऐसा नहीं करना चाहिए - ढांचा संभवतः यह सुनिश्चित नहीं कर सकता कि ग्राहक क्या करते हैं। :-) –

+0

@ मॉर्टन लॉरिट्सनहोडाबोकस: जाहिर है, एक हाइबरनेट लेनदेन में हजारों रिकॉर्ड लोड और संशोधित करना एक संकेत है कि एक अलग उपकरण का उपयोग किया जाना चाहिए। हां, * स्पष्ट रूप से * मेरा मतलब है कि 'बचाओ()' को कॉल करना है क्योंकि हाइबरनेट को गंदे इकाइयों को खोजने के लिए। –

+0

@MortenLauritsen Khodabocus कृपया मुझे प्रबुद्ध करें। एक लेनदेन में एक बड़े पढ़ने-योग्य डेटा सेट को संसाधित करना क्यों बुरा विचार होगा? ऐसा लगता है कि अगर यह डीबी पक्ष पर आदेश देने में शामिल था, तो यह स्मार्ट होगा क्योंकि यह कई बार पुन: व्यवस्थित करने की आवश्यकता से बचाएगा। लेनदेन का उपयोग नहीं करना मतलब है कि डीबी आपके आदेशित राज्य को विभिन्न प्रश्नों में याद रखेगा जो एक ही लेनदेन का हिस्सा हैं? साथ ही, 'एक लेनदेन का उपयोग' नहीं है, वास्तव में हाइबरनेट की स्क्रॉल करने योग्य रीसेट एपीआई क्या करता है? – KyleM

3

यहां एक और कारण है कि मैंने अभी भाग लिया: पिछले लेनदेन के दौरान कई बार संग्रहित प्रक्रिया को कॉल करते समय पिछले परिणामों को कैश करना। निम्नानुसार सरलीकृत कोड।

//Begin transaction 
SessionFactory sf = HibernateSessionFactory.getFactory(); 
Session dbSession = sf.getCurrentSession(); 
dbSession.beginTransaction(); 

//First call to stored procedure 
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA"); 
query.setString("custName", "A"); 
List<ShipSummaryRow> shipSummaryRows = query.list(); 

//Second call to stored procedure 
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA"); 
query.setString("custName", "B"); 
List<ShipSummaryRow> shipSummaryRows = query.list(); 

//Commit both  
dbSession.getTransaction().commit(); 

एक स्पष्ट() पहली कॉल के बाद बिना, पहली कॉल की resultset पंक्तियों दूसरी कॉल का resultset में दोहराया जाता है। मैं ओरेकल 11 जीआर 2 का उपयोग कर रहा हूँ।

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

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <class name="com.jfx.rr.model.ShipSummaryRow"> 
     <id name="id" type="integer"/> 
     <property name="shipQtrString" not-null="true" type="string"/> 
     <property name="shipAmount" not-null="true" type="double"/> 
    </class> 
    <sql-query callable="true" name="RR_CUST_OPP_DATA"> 
     <return class="com.jfx.rr.model.ShipSummaryRow"> 
      <return-property column="SHIPPED_ID" name="id"/> 
      <return-property column="SHIP_QTR" name="shipQtrString"/> 
      <return-property column="SHIPPED_AMOUNT" name="shipAmount"/> 
     </return> 
     { call RR_DASHBOARD_REPORTS_PKG.RR_CUST_OPP_DATA(?, :custName) } 
    </sql-query> 
</hibernate-mapping>