2012-06-12 74 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