【Hibernate框架】批量操做Batch總結

在咱們作.net系統的時候,所作的最多見的批量操做就是批量導入、插入、更新、刪除等等,之前咱們怎麼作呢?基本上有如下幾種方式:html

一、利用循環調用insert方法,一條條插入。java

 

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public boolean insertStudent(List<Student> studentList)  
  2. {  
  3.     try{  
  4.         if(studentList.count !=0){  
  5.             for(int i=0;i<studentList.count;i++){  
  6.                 //調用save方法  
  7.             }  
  8.                 return true;  
  9.                 }  
  10.     }catch(Exception ex){  
  11.         throw New Exception("插入失敗,請重試!")  
  12.         return false;  
  13.     }  
  14. }  



 


二、利用循環作sql語句拼接,而後批量執行sql語句。mysql

 

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public boolean insertStudent(List<Student> studentList)  
  2. {  
  3.     try{  
  4.         if(studentList.count !=0){  
  5.             stringBuffer strSqltxt="";  
  6.             for(int i=0;i<studentList.count;i++){  
  7.                 strSqltxt.append("insert into TableName (……) values (……);"  
  8.             }  
  9.             cmd.executesql(strSqltxt.toString());  
  10.         }  
  11.     }catch(Exception ex){  
  12.         throw New Exception("插入失敗,請重試!")  
  13.         return false;  
  14.     }  
  15. }  



 

但是,對於封裝比較完善的hibernate持久層,咱們又能怎麼作呢?web

       

       最多見的,也是利用循環來批量操做,可是,這裏有一個必需要注意的點,就是緩存或者說是session區的空間是有限的,禁不起咱們無限制的存放,因此,當咱們執行如下操做時,會拋異常,內存溢出OutOfMemoryException!sql

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. Session session = sessionFactory.openSession();  
  2. Transaction tx = session.beginTransaction();  
  3. for ( int i=0; i<100000; i++ ) {  
  4.     Customer customer = new Customer(.....);  
  5.     session.save(customer);  
  6. }  
  7. tx.commit();  
  8. session.close();  


這樣是不能夠的,可是在這時,hibernate也給咱們提供瞭解決方法,就是咱們能夠經過設置JDBC的批量抓去數量參數(batch size)來設置一個合適的值,好比說10-50-100不等,配置:數據庫

 

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <span style="font-size:18px;"><property name="hibernate.jdbc.batch_size">100</property></span>  

 

 

另外,咱們還能夠顯示的禁用二級緩存,之前咱們也提到過:緩存

<property name="hibernate.cache.use_second_level_cache">false</property>session

 

正確代碼:app

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. Session session = sessionFactory.openSession();  
  2. Transaction tx = session.beginTransaction();  
  3. for ( int i=0; i<100000; i++ ) {  
  4.     Customer customer = new Customer(.....);  
  5.     session.save(customer);  
  6.     if(i%100==0){//100, 和配置的JDBC batch size同樣  
  7.         session.fulsh();//刷出並同步到底層持久化, 批量的插入而且釋放內存:  
  8.         session.clear(); //徹底清除session  
  9.     }  
  10. }  
  11. tx.commit();  
  12. session.close();  

 

這樣就能解決咱們的那個內存溢出的問題,由於當你的存儲對象數超過你設定的能接受的合理值的時候,程序會自動將持久化對象flush進數據緩存起來,而後清空session,進行下一輪存儲,待全部數據所有完成,執行commit進行提交,數據庫更新數據,說的簡單,這樣的效率是不咋地的,不信你能夠試試,你想一想,先發出sql,100一輪,執行1000輪用來緩存sql語句,而後數據庫統一執行sql,時間啊!less

 

StatelessSession(無狀態session)接口

可是這不是問題,由於hibernate還給咱們提供了一個StatelessSession(無狀態session)接口,做爲選擇,Hibernate提供了基於命令的API:

一、能夠用detached object(託管對象)的形式把數據以流的方法加入到數據庫,或從數據庫輸出。

二、StatelessSession沒有持久化上下文,也不提供多少高層的生命週期語義。

三、無狀態session不實現第一級cache;

四、也不和第二級緩存交互,也不和查詢緩存交互。

五、它不實現事務化寫,也不實現髒數據檢查。

六、用stateless session進行的操做甚至不級聯到關聯實例。

七、stateless session忽略集合類(Collections)。

八、經過stateless session進行的操做不觸發Hibernate的事件模型和攔截器。

九、無狀態session對數據的混淆現象免疫,由於它沒有第一級緩存。

十、無狀態session是低層的抽象,和低層JDBC至關接近。換句話說,它能夠直接操做數據。

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. StatelessSession session = sessionFactory.openStatelessSession();  
  2. Transaction tx = session.beginTransaction();  
  3.      
  4. ScrollableResults customers = session.getNamedQuery("GetCustomers")  
  5.     .scroll(ScrollMode.FORWARD_ONLY);  
  6. while ( customers.next() ) {  
  7.     Customer customer = (Customer) customers.get(0);  
  8.     customer.updateStuff(...);  
  9.     session.update(customer);  
  10. }  
  11.      
  12. tx.commit();  
  13. session.close();  

 

 

DML(Data Manipulation Language數據操做語言)風格操做

再有就是特殊服務(業務需求)須要咱們採用DML(Data Manipulation Language數據操做語言)風格操做,從一張表導入另外一張表數據,比方說從學生表(T_Studeng)裏面往大三學生表(T_ThreeStudent)裏面倒數據.

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. Session session = sessionFactory.openSession();  
  2. Transaction tx = session.beginTransaction();  
  3.   
  4. String hqlInsert = "insert into ThreeStudent(id, name) select s.id, s.name from Student s where ...";  
  5. int createdEntities = s.createQuery( hqlInsert )  
  6.         .executeUpdate();  
  7. tx.commit();  
  8. session.close();  

 

 

以上就是對批量操做的一點總結,萬望對你們能有點幫助

相關文章
相關標籤/搜索