熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Spring+Hibernate處理大批量數據

2013-11-23 20:21:18  來源: Java開源技術 

  對象打包成List

  關於使用Spring+Hibernate進行大批量數據的插入和更新它的性能和使用JDBC PreparedStatement的batch批量操作以及數據庫的存儲過程操作幾乎可以一樣高在Hibernate的官方文檔裡說到了BatchprocessingSpring+Hibernate大批量處理數據想要說明如何使用Hibernate大批量處理數據獲得高性能

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

  Session session = sessionFactoryopenSession();

  Transaction tx = sessionbeginTransaction();

  for ( int i=; i<; i++ ) {

  Customer customer = new Customer();

  sessionsave(customer);

  }  mit();

  sessionclose();

  這段程序大概運行到 條記錄左右會失敗並拋出 內存溢出異常(OutOfMemoryException) 這是因為 Hibernate 把所有新插入的 客戶(Customer)實例在session級別的緩存區進行了緩存的緣故

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

  hibernatejdbcbatch_size

  你也可能想在執行批量處理時關閉二級緩存

  hibernatecacheuse_second_level_cache false

   批量插入(Batch inserts)

  如果要將很多對象持久化你必須通過經常的調用 flush() 以及稍後調用 clear() 來控制第一級緩存的大小

  Session session = sessionFactoryopenSession();

  Transaction tx = sessionbeginTransaction();

  for ( int i=; i<; i++ ) {

  Customer customer = new Customer();

  sessionsave(customer);

  if ( i % == ) { // same as the JDBC batch size //與JDBC批量設置相同

  //flush a batch of inserts and release memory:

  //將本批插入的對象立即寫入數據庫並釋放內存

  sessionflush();

  sessionclear();

  }  }

  mit();

  sessionclose();

   批量更新(Batch updates)

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

  Session session = sessionFactoryopenSession();

  Transaction tx = sessionbeginTransaction();

  ScrollableResults customers = sessiongetNamedQuery(GetCustomers)

  setCacheMode(CacheModeIGNORE)

  scroll(ScrollModeFORWARD_ONLY);

  int count=;  while ( customersnext() ) {

  Customer customer = (Customer) customersget();

  customerupdateStuff();

  if ( ++count % == ) {

  //flush a batch of updates and release memory:

  sessionflush();

  sessionclear();

  }  }

  mit();

  sessionclose();

   大批量更新/刪除(Bulk update/delete)

  就像已經討論的那樣自動和透明的 對象/關系 映射(object/relational mapping)關注於管理對象的狀態這就意味著對象的狀態存在於內存因此直接更新或者刪除 (使用 SQL語句 UPDATE 和 DELETE)數據庫中的數據將不會影響內存中的對象狀態和對象數據 不過Hibernate提供通過Hibernate查詢語言(第 章 HQL:Hibernate查詢語言)來執行大批量SQL風格的(UPDATE)和(DELETE) 語句的方法

  UPDATE 和 DELETE語句的語法為 (UPDATE | DELETE ) FROM? ClassName (WHERE WHERE_CONDITIONS)?有幾點說明

  在FROM子句(fromclause)中FROM關鍵字是可選的

  在FROM子句(fromclause)中只能有一個類名並且它不能有別名

  不能在大批量HQL語句中使用連接(顯式或者隱式的都不行)不過在WHERE子句中可以使用子查詢

  整個WHERE子句是可選的

  舉個例子使用QueryexecuteUpdate()方法執行一個HQL UPDATE語句

  Session session = sessionFactoryopenSession();

  Transaction tx = sessionbeginTransaction();

  String hqlUpdate = update Customer set name = :newName where name = :oldName;

  int updatedEntities = screateQuery( hqlUpdate )

  setString( newName newName )

  setString( oldName oldName )

  executeUpdate();

  mit();

  sessionclose();

  執行一個HQL DELETE同樣使用 QueryexecuteUpdate() 方法(此方法是為那些熟悉JDBCPreparedStatementexecuteUpdate() 的人們而設定的)

  Session session = sessionFactoryopenSession();

  Transaction tx = sessionbeginTransaction();

  String hqlDelete = delete Customer where name = :oldName;

  int deletedEntities = screateQuery( hqlDelete )

  setString( oldName oldName )

  executeUpdate();

  mit();

  sessionclose();

  由QueryexecuteUpdate()方法返回的整型值表明了受此操作影響的記錄數量注意這個數值可能與數據庫中被(最後一條SQL語句)影響了的數有關也可能沒有一個大批量HQL操作可能導致多條實際的SQL語句被執行舉個例子對joinedsubclass映射方式的類進行的此類操作這個返回值代表了實際被語句影響了的記錄數量在那個joinedsubclass的例子中對一個子類的刪除實際上可能不僅僅會刪除子類映射到的表而且會影響還有可能影響與之有繼承關系的joinedsubclass映射方式的子類的表

  注意上述大批量HQL操作的少數限制會在新版本中得到改進進一步詳細信息請參考JIRA裡的路線圖


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28366.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.