2012-03-15 19 views
5

मेरा आवेदन हाइबरनेट 3.2 और स्प्रिंग 2.5 पर आधारित है। यहाँ लेनदेन आवेदन संदर्भ से संबंधित टुकड़ा प्रबंधन है:हाइबरनेट और वसंत के साथ बैच सम्मिलन

<tx:annotation-driven transaction-manager="txManager"/> 
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
      <property name="sessionFactory" ref="sessionFactory"/> 
      <property name="nestedTransactionAllowed" value="true"/> 
    </bean> 
    <bean id="transactionTemplate" classs="org.springframework.transaction.support.TransactionTemplate"> 
      <property name="transactionManager" ref="txManager"/> 
    </bean> 
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/> 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="configLocation" value="classpath:/hibernate.cfg.xml"></property> 
    </bean> 

के लिए सभी डीएओ के प्रासंगिक सेवा वर्ग देखते हैं और लेन-देन सेवा परत में प्रत्येक विधि पर @Transactional का उपयोग कर वहाँ से नियंत्रित किया जाता। हालांकि अब एक परिदृश्य है कि डीएओ में एक विधि का कहना है कि सेवा परत से "पार्स()" कहा जाता है। सेवा परत में मैंने @Transactional(readOnly=false) निर्दिष्ट किया है। डीएओ में यह पार्स विधि एक और विधि कहती है, उसी डीएओ में "सेव()" कहती है जो डेटाबेस में बड़ी संख्या में पंक्तियां (लगभग 5000) स्टोर करती है। अब पार्स फ़ंक्शन से लूप में सेव विधि को कॉल किया जाता है। अब मुद्दा यह है कि "सेव" विधि के लिए लगभग 100 कॉल के बाद .. मुझे कभी-कभी आउटऑफमेमरी अपवाद मिलता है या कभी-कभी प्रोग्राम प्रत्युत्तर देना बंद कर देता है।

अभी के लिए इन परिवर्तनों को जो मैं बचाने के विधि करने के लिए बना दिया है:

Session session = getHibernateTemplate().getSessionFactory().openSession(); 
      Transaction tx = session.beginTransaction(); 

      int counter = 0; 
      if(books!=null && !books.isEmpty()){ 
       for (Iterator iterator = books.iterator(); iterator 
         .hasNext();) { 
        Book book = (Book) iterator.next(); 
        session.save(book); 
        counter++; 
        if(counter % 20==0) { 
         session.flush(); 
         session.clear(); 
        } 
       } 
      } 
      tx.commit(); 
     session.close(); 

यह मेरा आवेदन में केवल विधि जहां मैं इस तरह के लेन-देन शुरू करने और विधि के अंत में यह प्रतिबद्ध है। अन्यथा मैं आमतौर पर बस getHibernateTemplate.save() पर कॉल करता हूं। मुझे यकीन नहीं है कि मुझे @Transactional(readOnly=false, PROPOGATION=NEW) पर save() पर डीएओ में अलग से इस बचत विधि के लिए लेनदेन प्रबंधन करना चाहिए, या यह दृष्टिकोण ठीक है?

इसके अलावा मैंने hibernate.cfg कॉन्फ़िगरेशन फ़ाइल में hibernate.jdbc.batch_size से 20 को अद्यतन किया है।

कोई सुझाव?

उत्तर

0

मैं parse को इस तरह से दोबारा प्रतिक्रिया दूंगा कि यह सीधे save पर कॉल नहीं करता है लेकिन सेवा परत से कुछ कॉलबैक लेता है। सेवा परत इस लेनदेन के रूप में save कॉल के साथ अपनी लेनदेन विधि को पारित करेगी।

यह आपके मामले में बिल्कुल सही तरीके से काम नहीं कर सकता है लेकिन इस संक्षिप्त वर्णन से यह कुछ ऐसा होगा जो मैं कोशिश करूंगा।

1

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

5

हाइबरनेट साथ बैच प्रविष्टि के लिए, सबसे अच्छा अभ्यास, StatelessSession है यह आपके इकाई के किसी भी राज्यों को कैश doesn `t, आप OutOfMemory का सामना नहीं करेंगे, जैसे कोड:

if (books == null || books.isEmpty) { 
    return; 
} 
StatelessSession session = getHibernateTemplate().getSessionFactory().openStatelessSession(); 
Transaction tx = session.beginTransaction(); 

for (Book each : books) {   
    session.insert(book);   
} 
tx.commit(); 
session.close(); 

और StatelessSession का लेन-देन वर्तमान लेनदेन संदर्भ से स्वतंत्र है।

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