如題,有兩種方法java
1)使用FLUSH數據庫
2)使用JDBC小程序
分別來解釋:緩存
1)hibernate在進行數據庫操做的時候,都要有事務支持的。可能你曾遇到過,沒有加事務,程序會報錯的狀況。session
而事務每次提交的時候,都會和數據庫交互,即讓數據庫執行SQL語句。ide
在說到hibernate中的save() 或者saveOrUpdate()方法,其實,它們都是利用hibernate的一級緩存,在事務沒有提交的時候,全部對象,並無寫入數據庫。而是保存在內存中。在事務提交的時候,hibernate會把這些對象持久化到數據庫中。另外一方面,hibernate提供了一個顯式的API來強制寫數據庫。就是FLUSH。當程序執行session.flush(),就會持久化數據,而沒必要等到事務提交時才執行。性能
本人寫了一個DEMO,一個線程產生USER,一個保存USER。優化
生產者代碼以下:ui
package com.baidu.test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.baidu.model.User; public class test extends Thread { public static int count = 0; public static List<User> userlist = Collections.synchronizedList(new ArrayList()); public User user; public static void main(String[] args) { new test().start(); new HandleThread().start(); } public static int usercount=0; @Override public void run() { while (true) { try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } User t = new User(); t.setId(usercount); t.setUsername("name_" + usercount); userlist.add(t); System.out.println("生產出一個user_"+usercount); usercount++; } } }
消費者代碼以下:spa
package com.baidu.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.baidu.model.User; public class HandleThread extends Thread { @Override public void run() { boolean flag=false; Configuration config = new Configuration(); config.configure(); SessionFactory factory = config.buildSessionFactory(); Session session = factory.openSession(); while (true) { if (test.userlist.size() > 0) { for (int i = 0; i < test.userlist.size(); i++) { System.out.println("處理了" + test.userlist.get(i).getId()); insert(test.userlist.get(i),session); } test.userlist.clear(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if(flag) break; } session.close(); } public void insert(User user,Session session) { Transaction tran = session.beginTransaction(); session.save(user); if (test.count++ % 10 == 0) { System.out.println(test.count); session.flush(); session.clear(); } tran.commit(); } }
if (test.count++ % 10 == 0) { System.out.println(test.count); session.flush(); session.clear(); }這段代碼就是執行批量操做的核心。固然這個須要在hibernate配置文件中配置下 <property name="hibernate.jdbc.batch_size">10</property>這個值,從網上獲得的說法是一次推送SQL語句的條數。暫且相信了,後續我將驗證(經過抓包)。至此,第一種批量處理已經完成。2) to be continue...Hibernate批量處理其實從性能上考慮,它是很不可取的,浪費了很大的內存。從它的機制上講,Hibernate它是先把符合條件的數據查出來,放到內存當中,而後再進行操做。實際使用下來性能很是不理想,在筆者的實際 使用中採用下面的第三種優化方案的數據是:100000條數據插入數據庫,主流臺式機的配置,須要約30分鐘,呵呵,暈倒. 總結下來有三種來處理以解決性能問題: 1:繞過Hibernate API ,直接經過 JDBC API 來作,這個方法性能上是比較好的。也是最快的. 2:運用存儲過程。 3:仍是用Hibernate API 來進行常規的批量處理,能夠也有變,變就變在,咱們能夠在查找出必定的量的時候,及時的將這些數據作完操做就 刪掉,session.flush();session.evict(XX對象集); 這樣也能夠挽救一點性能損失。這個「必定的量」要就要根據實際狀況作定量參考了。通常爲30-60左右,但效果仍然不理想. 1:繞過Hibernate API ,直接經過 JDBC API 來作,這個方法性能上是比較好的,也是最快的。(實例爲 更新操做) Transaction tx=session.beginTransaction(); //注意用的是hibernate事務處理邊界 Connection conn=session.connection(); PreparedStatement stmt=conn.preparedStatement("update CUSTOMER as C set C.sarlary=c.sarlary+1 where c.sarlary>1000"); stmt.excuteUpdate(); tx.commit(); //注意用的是hibernate事務處理邊界 這小程序中,採用的是直接調用JDBC 的API 來訪問數據庫,效率很高。避免了Hibernate 先查詢出來加載到內存,再進行操做引起的性能問題 。 2:運用存儲過程。但這種方式考慮到易植和程序部署的方便性,不建議使用.(實例爲 更新操做) 若是底層數據庫(如Oracle)支持存儲過程,也能夠經過存儲過程來執行批量更新。存儲過程直接在數據庫中運行,速度更加快。在Oracle數 據庫中能夠定義一個名爲batchUpdateCustomer()的存儲過程,代碼以下: 代碼內容 create or replace procedure batchUpdateCustomer(p_age in number) as begin update CUSTOMERS set AGE=AGE+1 where AGE>p_age; end; 以上存儲過程有一個參數p_age,表明客戶的年齡,應用程序可按照如下方式調用存儲過程: 代碼內容 tx = session.beginTransaction(); Connection con=session.connection(); String procedure = "{call batchUpdateCustomer(?) }"; CallableStatement cstmt = con.prepareCall(procedure); cstmt.setInt(1,0); //把年齡參數設爲0 cstmt.executeUpdate(); tx.commit(); 從上面程序看出,應用程序也必須繞過Hibernate API,直接經過JDBC API來調用存儲過程。 3:仍是用Hibernate API 來進行常規的批量處理,能夠也有變,變就變在,咱們能夠在查找出必定的量的時候,及時的將這些數據作完操做就 刪掉,session.flush();session.evict(XX對象集); 這樣也能夠挽救一點性能損失。這個「必定的量」要就要根據實際狀況作定量參考了。。 (實例爲 保存操做) 業務邏輯爲:咱們要想數據庫插入10 0000 條數據 tx=session.beginTransaction(); for(int i=0;i<100000;i++) { Customer custom=new Customer(); custom.setName("user"+i); session.save(custom); if(i%50==0) // 以每50個數據做爲一個處理單元,也就是我上面說的「必定的量」,這個量是要酌情考慮的 { session.flush(); session.clear(); } } 這樣能夠把系統維持在一個穩定的範圍....