2016-09-24 70 views
1

當通過「數據提供者」進行流式處理時,我需要在數據庫中插入相當多的實體,例如大約100.000。這整個步驟需要是事務性的。
爲了簡化我的用例,儘可能讓我們假設這是我的代碼:插入大量行而不將實體附加到持久性上下文

@Transactional 
public void execute() { 
    for (int i = 0; i < 100000; i++) { 
     carRespository.save(new Car()); 
    } 
} 

這段代碼的問題是,即使很清楚我有沒有用在汽車實體後插入查詢生成的實體附加到持久性上下文並保存在內存中,直到事務完成。
我想確保在垃圾收集被觸發的情況下,創建的實體被清除。對於這個目前我看到了兩個解決方案:

  • 在存儲庫中創建一個本地插入查詢
  • 注入EntityManager在服務和呼叫後,每em.detach(car)插入

我傾向於選擇第二個選項因爲我不需要在實體更改時管理本機插入語句。

你能確認我採取了正確的做法還是建議一個更好的選擇。

回答

2

您可以在Hibernate documentation找到插入批處理數據的方法。

當爲了控制第一級緩存的大小而定期創建新的對象持久刷新()然後清除()會話時。

因此,下面的方法建議:

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 

for (int i=0; i<100000; i++) { 
    session.save(new Car()); 
    if (i%20 == 0) { 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 
+0

這將是實施的「純」休眠方式我第二個建議(帶分離的一個)。我承認你的建議是「偶爾一次」清除實體。我也可以用'em.clear()'來實現這一點。 – mvlupan

0

您可以嘗試使用saveAndFlush(S entity)方法從春天數據JPA JpaRepository而不是save()

+0

從我的理解,這將沖刷到現場的數據庫插入。我對該部分沒有任何問題:從我的角度來看,這可以是單個插入或批量插入。我感興趣的是確保實體可用於gc的最佳方式是什麼。 – mvlupan

相關問題