hibernate 批量插入數據

如題,有兩種方法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(); } } 這樣能夠把系統維持在一個穩定的範圍....
相關文章
相關標籤/搜索