2011-05-30 12 views
7

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

टेबल्स और संबंधों

शाखाकई उत्पाद, उत्पादकई शाखाओं में हैं कर रहे हैं।

उत्पादकई उत्पाद है, और एक श्रेणीकई उत्पाद

और वहाँ अधिक तालिकाओं कि वहाँ थे और ठीक से काम कर रहे हैं है।

नई टेबल/वस्तुओं है कि मैं बनाया शाखा, उत्पाद, BranchToProduct हैं।

उत्पाद BranchToProduct वस्तुओं, जो 3 क्षेत्रों

मैं जानकारी मैं फ़ाइल की प्रत्येक पंक्ति से प्राप्त से भरा 3 क्षेत्रों के साथ, उत्पाद के सेट करने के लिए BranchToProduct वस्तुओं को जोड़ने की आवश्यकता है का एक सेट है।

मैं एक सरल रेखा जोड़ सकते हैं और आवेदन फेंकता है:

उत्पाद = productDAO.findByModel (stringModel);

lazily भूमिका का एक संग्रह प्रारंभ करने में विफल: com.bamboo.catW3.domain.Product.products, कोई सत्र या सत्र

बंद हो गया तो मैं मानचित्रण (HBM फ़ाइल) हाइबरनेट करने के लिए जाना और संबंध product_to_products आलसी = झूठी सेट करें, लाइन अकेले ठीक चलती है, लेकिन अगर मैं इसे फ़ाइल चक्र पर रखने की कोशिश करता हूं तो एप्लिकेशन हमेशा 18 वें लाइन पर संसाधित होने पर लटकता है, इससे कोई फर्क नहीं पड़ता कि मैं किस फाइल का उपयोग करता हूं या ऑर्डर सामग्री, कंसोल काम करना बंद कर देता है, प्रक्रिया को मारने वाले जावा को बंद करना होगा।

किसी भी तरह से, डिबग में, मैं HQL का एक सरल खोज के लिए की एक बहुत कुछ मिलता है HQL की 13 लाइनों जब तक, मैं अपने त्रुटि मिलती है जब आलसी = सच है, और लाइनों जब मैं आलसी = false का उपयोग का एक बहुत और पर डाल दिया साईकिल।

मुझे लगता है कि मुझे समस्या को आलसी = सत्य के साथ ठीक करने का प्रयास करना चाहिए।

यह स्थिति मुझे सोचने पर मजबूर:

1.- जब आलसी = सच। मैं इस विधि की इस पंक्ति की एक पंक्ति को कैसे चला सकता हूं, लेकिन यह कक्षा के अन्य तरीकों पर ठीक काम करता है?(CategoryFacade, ContainerFacade, ProductFacade, ProductOptionFacade, ProductStatusFacade, UserFacade, EmailFacade, FileFacade, BranchOfficeFacade)

इस के लिए कोड है:

वैसे, यह एक वर्ग CatalogFacade कहा जाता है कि अन्य clasess के तरीकों को लागू करता है
productDao.find():

public Product find(Integer id) throws DataAccessException { 

     Product product= (Product) super.find(Product.class, id); 


     if(product!=null){ 
      product.setProductAttributes(new TreeSet<ProductAttribute>(product.getProductAttributes())); 

      for (Product ptp : product.getProducts()){ 
       ptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())); 

      } 

     } 

अपवाद के लिए पिछले पर सही इस पंक्ति में डाल दिया गया है,:

pptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())) 

Intelij के डीबगर में, मैं वस्तु को गलत तरीके से क्वेरी से बनते देख सकते हैं:)

product.getProducts (= {[email protected]}unable अभिव्यक्ति विधि फेंक दिया मूल्यांकन करने के लिए 'org.hibernate LazyInitializationException 'अपवाद।

कैसे कभी अन्य विशेषताओं ठीक हैं। इस उत्पाद में डेटाबेस में अन्य उत्पाद भी नहीं हैं। (पूर्णांक)

अद्यतन

स्थिति पर गहन जानकारी के,

product.find अंदर

लाइन में इससे पहले कि मैं अपवाद मिलता है, हम पर देख सकते हैं डीबग कि product.products सरणी में एक त्रुटि है, उस मूल्य के बजाय आप आलसी प्रारंभिक अपवाद देख सकते हैं। कैसे, अगर मैं इसे किसी अन्य विधि से कॉल करता हूं, तो सरणी मिलती है। तो क्या यह हालांकि यहां तक ​​कि विधि केवल एक पूर्णांक प्राप्त करता है के अंदर नहीं हो सकता।

इसके अलावा, हमने पाया है कि इस आवेदन के सभी जीवन चक्र के साथ हुआ है, कुछ समय स्टाफ बस की तरह है, लेकिन यह इस भ्रष्ट सरणियों को अशक्त सेटिंग को बदलने के लिए एक विधि दोहराया। तो मुझे 100% यकीन है कि यह एप्लिकेशन अधिक संसाधनों का उपभोग कर रहा है, तो इसे चाहिए।

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

अधिक जानकारी जोड़ना। यह कैसे produt.find AbstractDAOImpl में कार्यान्वित किया जाता है:

public final Object find(Class clazz, Integer id) throws DataAccessException{ 

     return getHibernateTemplate().get(clazz,id); 
} 

और इस मेरे लेन-देन प्रबंधक कॉन्फ़िगरेशन, एनोटेशन विधि प्रोत्साहन से पहले उत्तर में वर्णित काम नहीं किया है:

<bean id="catalogFacade" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager"> 
     <ref local="transactionManager"/> 
    </property> 
    <property name="target"> 
     <ref local="catalogFacadeTarget"/> 
    </property> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="add*">PROPAGATION_REQUIRED</prop> 
      <prop key="save*">PROPAGATION_REQUIRED</prop> 
      <prop key="update*">PROPAGATION_REQUIRED</prop> 
      <prop key="delete*">PROPAGATION_REQUIRED</prop> 
      <prop key="remove*">PROPAGATION_REQUIRED</prop> 
      <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="contains*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="login*">PROPAGATION_SUPPORTS,readOnly</prop> 
     </props> 
    </property> 
</bean> 

उत्तर

0

मैंने पहले ही समस्या मिला है, और विभिन्न हाइबरनेट तरीकों का उपयोग करके यह तय की। मैं

getHibernateTemplate().loadAll(class) 

का उपयोग कुछ के सभी प्राप्त करने के लिए, और

getHibernateTemplate().get(class, id) 

एक भी बात खोजने के लिए।मैं दोनों में कोई समस्या नहीं है। मैंने पाया कि .find() मुझे देता है कि सत्र बंद त्रुटि था।

मैंने वास्तव में यह क्यों नहीं देखा है कि यह क्यों है।

एक अन्य विधि का उपयोग करने के अलावा मैं एकमात्र अन्य विकल्प सोच सकता हूं कि सत्र खोलना और बंद करना है, लेकिन मुझे लगता है कि आप ऐसा नहीं करना पसंद करते हैं।

+0

असल में यह है कि प्रोग्राम पहले से ही यह कैसे कर रहा है, अद्यतन कोड – Ernest

19

आपको आलसी प्रारंभिक अपवाद मिल रहा है क्योंकि उत्पाद के सदस्य चरों तक पहुंचने से पहले आपका सत्र बंद हो रहा है। जब निम्न पंक्ति निष्पादित होने

Product product= (Product) super.find(Product.class, id) 

हाइबरनेट एक सत्र को खोलता है, आप जो खोज रहे हैं, तो उसके बाद सत्र बंद कर देता है प्राप्त करता है। आलसी = सत्य वाले किसी भी फ़ील्ड इस समय पुनर्प्राप्त नहीं किया गया है; इसके बजाय, इन क्षेत्रों को प्रॉक्सी द्वारा आबादी दी जाती है। जब आप प्रॉक्सी ऑब्जेक्ट के वास्तविक मान को पुनर्प्राप्त करने का प्रयास करते हैं, तो यह डेटा पुनर्प्राप्त करने के लिए सक्रिय सत्र का उपयोग करके डेटाबेस पर वापस जाने का प्रयास करेगा। यदि कोई सत्र नहीं मिल पाता है, तो आपको वह अपवाद मिलता है जिसे आप देख रहे हैं। आलसी = सत्य को सेट करने के फायदे हैं क्योंकि यह पूरे ऑब्जेक्ट ग्राफ़ को तुरंत लोड होने से रोकता है; नेस्टेड ऑब्जेक्ट्स अकेले ही छोड़े जाते हैं जब तक आप उन्हें विशेष रूप से नहीं पूछते।

आपकी समस्या से निपटने के लिए दो आम तकनीकें हैं। सबसे पहले आप पहले ही पहचान चुके हैं, जो आलसी = झूठी सेटिंग कर रहा है। यह ठीक है अगर किसी उत्पाद में हमेशा उत्पाद विशेषताओं होते हैं, और आप आम तौर पर एक उत्पाद और इसके गुणों का एक साथ उपयोग करते हैं। यदि आपको अक्सर इसके गुणों के बिना उत्पाद ऑब्जेक्ट की आवश्यकता होती है, तो आप अनावश्यक डेटाबेस लोड बना रहे हैं।

दूसरी तकनीक स्प्रिंग एनोटेशन का उपयोग करके एक विधि को लेनदेन के रूप में चिह्नित करना है।

@Transactional 
public Product find(Integer id) throws DataAccessException { 

} 

कुछ नोट:

  1. आप काम (@Transactional एनोटेशन पर्याप्त नहीं है) करने के लिए लेन-देन के लिए कुछ अतिरिक्त विन्यास की जरूरत है। अधिक जानकारी के लिए here देखें।
  2. सर्वोत्तम प्रथाओं का निर्देश है कि आप अपनी डेटा एक्सेस परत की बजाय अपनी सेवा परत में विधियों को एनोटेट करते हैं।
+0

हैलो फिलिप देखें, मैंने आपके द्वारा उल्लेख की जाने वाली 2 विधियों का प्रयास किया है।पहला डेटाबेस डेटाबेस में 18 वें कॉल के बाद ऐप को लटकाता है, एनोटेशन काम नहीं करता है, और फिर भी यह बहुत अजीब है क्योंकि यह विधि उसी विधि के अन्य तरीकों पर अलग-अलग कॉल के लिए काम करती है जो इस विधि को अभी कॉल करती है। मैं अपने पहलू विन्यास को जोड़ने जा रहा हूं और देखता हूं कि यह मदद करता है या नहीं। मैं और क्या देख सकता हूं? – Ernest

+0

18 वीं कॉल के बाद हैंग द्वारा आपका क्या मतलब है? साथ ही, क्या आप अपने कैटलॉगफैक्ड में उत्पाद गुणों के माध्यम से या डीएओ में साइकिल चलाना चाहते हैं? – Fil

+0

अब तक प्रश्न में आपकी टिप्पणियां, डीबगर के माध्यम से आलसी लोड किए गए क्षेत्र का निरीक्षण करने से एक आलसी शुरुआत शुरू हो जाएगी जैसा कि एप्लिकेशन स्वयं ही करेगा; एक tranasaction के बाहर पुनर्प्राप्ति प्रयास किया जा रहा है। उत्पाद विशेषताओं पर आलसी = झूठी सेटिंग आपके लिए काम कर रही है? – Fil

0

प्राप्त विधि के साथ लोड विधि बदलें ..

मैं और अधिक अनुसंधान कर कि लोड विधि वास्तव में डेटाबेस से वस्तु लोड नहीं करता है के बाद पता चला। इसके बजाय यह स्वचालित रूप से प्रॉक्सी ऑब्जेक्ट देता है। लोड मानता है कि ऑब्जेक्ट पहले से ही "डेटाबेस से प्राप्त" हो गया है और कैश में है।

यदि आप यह सुनिश्चित करना चाहते हैं कि आप डेटाबेस को हिट करें, और सुनिश्चित करें कि आप इन 2 विधियों के बीच अंतर जानते हैं तो बस लोड के बजाय प्राप्त करें।

स्रोत: this spring forum comment

मैं व्यक्तिगत रूप से यह परीक्षण किया है और यह सही है, लोड विधि डीबी से सभी वांछित डेटा पुनः प्राप्त नहीं है। मेरी समस्या तय करने का उपयोग करना।

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