1. 程式人生 > >Spring+Hibernate處理大批量資料

Spring+Hibernate處理大批量資料

原文:http://blog.csdn.net/ye1992/article/details/9291237

關於使用spring+hibernate進行大批量資料的插入和更新,它的效能和使用JDBC 

PreparedStatement的batch批量操作以及資料庫的儲存過程操作幾乎可以一樣高。在Hibernate的官方文件裡說到了BatchprocessingSpring+Hibernate大批量處理資料想要說明如何使用Hibernate大批量處理資料獲得高效能。

使用Hibernate將 100 000 條記錄插入到資料庫的一個很自然的做法可能是這樣的

Session session = sessionFactory.openSession();  Transaction tx = session.beginTransaction();  for ( int i=0; i<100000; i++ ) {      Customer customer = new Customer(.....);      session.save(customer);  }  tx.commit();  session.close();

這段程式大概執行到 50 000條記錄左右會失敗並丟擲 記憶體溢位異常(OutOfMemoryException) 。這是因為 Hibernate 把所有新插入的 客戶(Customer)例項在session級別的快取區進行了快取的緣故。

我們會在本章告訴你如何避免此類問題。首先,如果你要執行批量處理並且想要達到一個理想的效能,那麼使用JDBC的批量(batching)功能是至關重要。將JDBC的批量抓取數量(batch size)引數設定到一個合適值(比如,10-50之間):

hibernate.jdbc.batch_size 20

你也可能想在執行批量處理時關閉二級快取:

hibernate.cache.use_second_level_cache false

14.1. 批量插入(Batch inserts)

如果要將很多物件持久化,你必須通過經常的呼叫 flush() 以及稍後呼叫 clear() 來控制第一級快取的大小。

Session session = sessionFactory.openSession();  Transaction tx = session.beginTransaction();       for ( int i=0; i<100000; i++ ) {      Customer customer = new Customer(.....);      session.save(customer);      if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20,與JDBC批量設定相同          //flush a batch of inserts and release memory:          //將本批插入的物件立即寫入資料庫並釋放記憶體          session.flush();          session.clear();      }  }       tx.commit();  session.close();

14.2. 批量更新(Batch updates)

此方法同樣適用於檢索和更新資料。此外,在進行會返回很多行資料的查詢時,你需要使用 scroll() 方法以便充分利用伺服器端遊標所帶來的好處。

Session session = sessionFactory.openSession();  Transaction tx = session.beginTransaction();       ScrollableResults customers = session.getNamedQuery("GetCustomers")      .setCacheMode(CacheMode.IGNORE)      .scroll(ScrollMode.FORWARD_ONLY);  int count=0;  while ( customers.next() ) {      Customer customer = (Customer) customers.get(0);      customer.updateStuff(...);      if ( ++count % 20 == 0 ) {          //flush a batch of updates and release memory:          session.flush();          session.clear();      }  }       tx.commit();  session.close();