2010-06-02 100 views
5

我有一个可怕的问题,希望有一个非常简单的答案。我的计算机运行时内存不足,我执行基本加载Java实体时内存不足

如果我有这样的代码:

MyEntity myEntity; 
for (Object id: someIdList) { 
    myEntity = find(id); 
    // do something basic with myEntity 
} 

而find()方法是一个标准的EntityManager相关的方法:

public MyEntity find(Object id) { 
    return em.find(mycorp.ejb.entity.MyEntity.class, id); 
} 

这代码在几周前工作,并且如果数据库中的项目较少,则工作正常。我对着产生的错误是:

java.lang.OutOfMemoryError:GC开销超过限制

唯一的例外是Oracle TopLink的调用某些Oracle JDBC方法来。

循环存在是因为诸如“从MyEntity中选择对象(o)为o”的EJBQL会在有很多记录时超载应用程序服务器。

+0

执行em.clear()不是我正在寻找的答案...但我会牢记它。 这个问题的问题是,它曾经工作......具有相同级别的数据库条目! 这又提出了另一个问题 - 如果我有一个循环,我可以定期刷新/清除..但是当应用程序只是长时间运行时怎么办? EntityManager应该管理它管理的多少! – 2010-06-03 14:07:38

+0

'EntityManager'大部分时间都是短生命周期(常见模式是* entitymanager-per-request *)。我建议阅读[5.1。实体经理和交易范围](http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html_single/#transactions-basics)。如果你不遵循这种模式,那么你将不得不处理“内存处理”。 EntityManager使内存中的实体保持跟踪更改,这就是JPA的工作方式,您不能合理地期望EntityManager能够加载整个数据库或为您刷新更改和分离实体。 – 2010-06-03 14:34:47

回答

8

This code worked a couple of weeks ago, and works fine if there are fewer items in the database. The resulting error I am facing is: java.lang.OutOfMemoryError: GC overhead limit exceeded

而这里并没有什么奇怪的。由em.find()加载的实体被放置并保存在持久化上下文中(在内存中)以跟踪更改,因此如果您在没有预防措施的情况下批量加载太多实体,就会爆炸您的内存并获得OOME。

如果你真的需要做的所有实体,需要调用flush()第一推及所有对数据库的修改然后clear()清除持久性上下文和定期释放内存的东西:

int i = 0; 
for (Object id: someReallyBigIdList) { 
    myEntity = find(id); 
    // do something basic with myEntity 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of DML operations and release memory: 
     em.flush(); 
     em.clear(); 
    } 
    i++; 
} 

调用clear()原因所有被管理的实体,成为超脱。对未被刷新到数据库的实体所做的更改不会被保留因此需要flush()的变化首先是

4

问题是,如果您执行循环,则只需查询一个接一个的实体,但它仍在您的EntityManager中被引用。您必须

  • 明确()EntityManager的,或
  • 从中取出实体(忘了这个函数如何被调用)。

这也是只读如果可能的话设置实体管理器是一个好主意,因为持有的每个记忆了对象的副本,只是为了检测是否有以冲洗的情况下可能发生的变化停止JPA ()到数据库。

+0

我刚在Hibernate中遇到一个问题,将实体设置为只读并不意味着它会停止持久上下文以在持久上下文中保存副本,它仍然会保留,因为随后的加载/查找将从持久上下文中获取副本的数据库。 – GMsoF 2016-08-30 02:14:46