2016-06-24 60 views
3

我有3個表中插入/更新超過15000行的要求。所以這是總共45k插入。使用無狀態會話批量插入/更新 - 休眠

在線上閱讀後,我在休眠狀態下使用了Statelesssession,因爲它沒有上下文緩存,所以它是批處理的最佳選擇。

session = sessionFactory.openStatelessSession; 
for(Employee e: emplList) { 
    session.insert(e); 
} 
transcation.commit; 

但是這段代碼需要一個多小時才能完成。

有沒有辦法一次保存所有實體對象? 保存整個集合,而不是一個一個地去做?

編輯:有沒有其他框架可以提供快速插入?

乾杯!

+0

你有沒有用簡單的Session試過'hibernate.order_inserts'和'hibernate.order_updates'?你可以在保存一個員工時顯示執行SQL語句嗎? –

回答

1

你需要確保你已經設置休眠屬性:

hibernate.jdbc.batch_size

讓Hibernate可以批這些插入,否則他們將一次完成一個。

+0

我厭倦了這個正常的會話,它仍然需要相同的時間或關閉。 –

1

無法一次插入所有實體。即使您可以在內部執行類似session.save(emplList)的任何操作,Hibernate也會一一保存。

因此Hibernate的用戶指南StatelessSession不使用批處理功能:

插入(),更新()和刪除()由StatelessSession接口定義的操作直接在數據庫中的行操作。它們導致相應的SQL操作立即執行。它們與Session接口定義的save(),saveOrUpdate()和delete()操作有不同的語義。

取而代之的是使用正常的會話並不時清除緩存。實際上,我建議你先測量你的代碼,然後進行修改,比如使用hibernate.jdbc.batch_size,這樣你可以看到有多少調整改善了你的負載。

嘗試改變它像這樣:

session = sessionFactory.openSession(); 
int count = 0; 
int step = 0; 
int stepSize = 1_000; 
long start = System.currentTimeMillis(); 
for(Employee e:emplList) { 
    session.save(e); 
    count++; 
    if (step++ == stepSize) { 
     long elapsed = System.currentTimeMillis() - start; 
     long linesPerSecond = stepSize/elapsed * 1_000; 
     StringBuilder msg = new StringBuilder(); 
     msg.append("Step time: "); 
     msg.append(elapsed); 
     msg.append(" ms Lines: "); 
     msg.append(count); 
     msg.append("/"); 
     msg.append(emplList.size()); 
     msg.append(" Lines/Seconds: "); 
     msg.append(linesPerSecond); 
     System.out.println(msg.toString()); 
     start = System.currentTimeMillis(); 
     step = 0; 
     session.clear(); 
    } 
} 
transcation.commit; 

關於hibernate.jdbc.batch_size - 你可以嘗試不同的值,其中包括一些非常大的取決於使用和網絡配置基礎數據庫。例如,對於應用服務器和數據庫服務器之間的1gbps網絡,我確實使用了10,000的值,每秒給我提供20,000條記錄。

stepSize更改爲相同的值hibernate.jdbc.batch_size

+0

所以基本上你說我不能減少這些插入的時間。有沒有其他框架提供這樣的東西? –

+0

不是的,因爲它是基於jdbc的。 – DiogoSantana

+0

使用批量jdbc批量插入可以使其更快。只需使用正常的Hibernate Session並更改'hibernate.jdbc_batch_size'。 – DiogoSantana