2012-03-15 30 views
5

Ứ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?

Trả lời

0

Tôi sẽ refactor parse theo cách nó không gọi trực tiếp save nhưng phải thực hiện một số cuộc gọi lại từ lớp dịch vụ. Lớp dịch vụ sẽ chuyển giao phương thức giao dịch của mình với cuộc gọi save làm cuộc gọi lại này.

Nó có thể không hoạt động chính xác như được giải thích trong trường hợp của bạn, nhưng từ mô tả ngắn này, đây sẽ là điều tôi muốn thử.

1

Bạn chỉ cần bit bằng cách xả và xóa phiên. Rời khỏi quản lý giao dịch cho Spring. Sử dụng sessionFactory.getCurrentSession() để đến phiên mà Spring đã mở cho bạn. Ngoài ra, đề xuất gần đây của Spring là tránh HibernateTemplate và làm việc trực tiếp với API của Hibernate. Tiêm SessionFactory cho dao-đậu của bạn.

5

Đối với sự chèn hàng loạt với chế độ ngủ đông, việc thực hành tốt nhất là StatelessSession, nó doesn `t cache bất kỳ quốc gia của tổ chức của bạn, bạn sẽ không gặp OutOfMemory, các mã như:

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(); 

Và Giao dịch StatelessSession độc lập với bối cảnh giao dịch hiện tại.

Các vấn đề liên quan