Ứng dụng của tôi dựa trên Hibernate 3.2 và Spring 2.5. Đây là công tác quản lý giao dịch đoạn mã liên quan đến từ bối cảnh ứng dụng:Batch Insertions với Hibernate & Spring
<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>
Đối với tất cả các nhân có lớp dịch vụ có liên quan và các giao dịch được xử lý có sử dụng @Transactional
trên mỗi phương pháp trong các lớp dịch vụ DAO. Tuy nhiên có một kịch bản bây giờ là một phương pháp trong DAO nói "parse()" được gọi từ lớp dịch vụ. Trong lớp dịch vụ tôi đã chỉ định @Transactional(readOnly=false)
. Phương thức phân tích cú pháp này trong DAO gọi một phương thức khác nói "save()" trong cùng một DAO lưu trữ một số lượng lớn các hàng (khoảng 5000) trong cơ sở dữ liệu. Bây giờ phương thức save được gọi trong một vòng lặp từ hàm phân tích cú pháp. Bây giờ vấn đề là sau khoảng 100 cuộc gọi đến phương thức "lưu" .. đôi khi tôi nhận được Ngoại lệ OutOfMemory hoặc đôi khi chương trình ngừng phản hồi.
Còn bây giờ đó là những thay đổi mà tôi đã thực hiện cho các phương pháp tiết kiệm:
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();
Đây là phương pháp duy nhất trong ứng dụng của tôi, nơi tôi bắt đầu một giao dịch như thế này và cam kết nó ở phần cuối của phương pháp. Nếu không, tôi thường chỉ gọi getHibernateTemplate.save()
. Tôi không chắc liệu mình có nên thực hiện quản lý giao dịch cho phương thức lưu này riêng biệt trong DAO hay không bằng cách đặt @Transactional(readOnly=false, PROPOGATION=NEW)
trên save()
hoặc cách tiếp cận này có được không?
Ngoài ra tôi đã cập nhật hibernate.jdbc.batch_size
thành 20 trong tệp cấu hình hibernate.cfg.
Mọi đề xuất?