2012-06-12 76 views
3

我在具有MySQL 5.0數據庫的WebSphere Application Server 8上使用OpenJPA 2.2.0。OpenJPA合併/持久化非常緩慢

我有我想要合併到數據庫中的對象的列表。

它像:

for (Object ob : list) { 
      Long start = Calendar.getInstance().getTimeInMillis(); 
      em = factory.createEntityManager(); 
      em.getTransaction().begin(); 

      em.merge(ob); 

      em.getTransaction().commit(); 
      em.close(); 
      Long end = Calendar.getInstance().getTimeInMillis(); 
      Long diff = end - start; 
      LOGGER.info("Time: " + diff); 
     } 

當我運行這個循環,我需要大約300-600毫秒合併一個對象。當我刪除行「em.merge(ob);」那麼我需要「0」毫秒來迭代1個List對象。

所以我的問題是:我能做些什麼來改善合併一個對象的時間?

謝謝!

+2

打開SQL登錄,查看生成了哪些請求,並查看哪些需要花費時間和原因。 –

回答

6

您可以嘗試在迭代&之前開始事務,然後在單個事務中提交事務。所以,基本上你正在創建一個批處理,這個批處理將在提交時被合併/保持。

此外,您可以限制一個批次中要處理的對象數&可以將更改顯式刷新到數據庫中。

在這裏,您將啓動一個事務&在每次迭代中提交併且每次創建/關閉實體管理器都會影響大量數據的性能。

它會像下面的代碼。

em = factory.createEntityManager(); 
em.getTransaction().begin(); 
int i = 0; 

    for (Object ob : list) { 
     Long start = Calendar.getInstance().getTimeInMillis(); 

     em.merge(ob); 

     Long end = Calendar.getInstance().getTimeInMillis(); 
     Long diff = end - start; 
     LOGGER.info("Time: " + diff); 

     /*BATCH_SIZE is the number of entities 
      that will be persisted/merged at once */ 

     if(i%BATCH_SIZE == 0){  
      em.flush(); 
      em.clear(); 
     } 

     i++; 
    } 

em.getTransaction().commit(); 
em.close(); 

在這裏,如果任何對象無法保留/合併,您也可以回滾整個事務。

+0

謝謝,我之前已經嘗試過,但合併的對象越多,我的列表中就會包含4000個對象 – veote

+0

@veote正如我已經提到的,您可以明確限制實體的數量。添加批處理邏輯以編碼,您可以指定適當的批處理大小(例如,取100,然後對100個實體的更改將立即反映在數據庫中),請參閱代碼。 –

+0

非常感謝,這個作品相當不錯! – veote