私のアプリケーションはHibernate3.2とSpring2.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>
すべてのDAOには、関連するServiceクラスがあり、トランザクションは@Transactional
、サービスレイヤーの各メソッドを使用してそこで処理されます。ただし、DAOのメソッドが「parse()」と言うシナリオがサービスレイヤーから呼び出されるようになりました。サービスレイヤーで指定し@Transactional(readOnly=false)
ました。DAOのこの解析メソッドは、データベースに多数の行(約5000)を格納する同じDAOの「save()」という別のメソッドを呼び出します。これで、saveメソッドがparse関数からループで呼び出されます。ここで問題となるのは、「save」メソッドを約100回呼び出した後、OutOfMemory例外が発生したり、プログラムが応答しなくなったりすることがあります。
今のところ、これらは私がsaveメソッドに加えた変更です:
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)
を配置することにより、DAOでこの保存方法のトランザクション管理を個別に実行する必要があるかどうかわかりませんsave()
。それともこのアプローチで問題ありませんか?
hibernate.jdbc.batch_size
また、hibernate.cfg構成ファイルのを20に更新しました。
助言がありますか?