2011-04-15 67 views
3

我在表中有1M行,我想获得所有这些行。但是,当我试图通过分页获得所有与jpa的行,然后我得到java堆错误。你认为我错过了什么吗?任何意见java持久性内存泄漏

int counter = 0; 
while (counter >= 0) { 
    javax.persistence.EntityManager em = javax.persistence.Persistence 
    .createEntityManagerFactory("MyPU") 
    .createEntityManager(); 

    Query query = em.createQuery("select m from mytable m"); 
    java.util.Collection<MyEntity> data = query 
      .setFirstResult(counter).setMaxResults(1000).getResultList(); 
    for(MyEntity yobj : data){ 
      System.out.println(obj); 
    } 
    counter += 1000; 
    data.clear(); 
    em.clear(); 
    em.close(); 
} 
+0

您是否尝试使用-Xmx增加堆大小的最大值?请参阅:http://javahowto.blogspot.com/2006/06/6-common-errors-in-setting-java-heap.html – Teetrinker 2011-04-15 10:47:24

回答

1

由于您使用本地SQL,无论如何,你不能指定LIMIT :counter, 1000(或ROWNUM BETWEEN :counter AND 1000如果使用Oracle)直接在SQL语句?

+0

那么,我正在使用MySQL,我们可以指定限制,但它不被JPA允许。 JPA提供了一种机制来通过设置firstResutl进行分页并设置Max Result,但是当计数器达到250,000时,它会抛出堆异常 – user704006 2011-04-15 10:15:42

+2

是的,一些JPA实现会在内存中分页,而不是让数据库执行该操作,这是当然是废话。它是否与'EntityManager.createNativeQuery()'一起工作? – 2011-04-15 10:19:40

+0

唯一的方法是使用本机查询分页来防止内存泄漏。它的工作原理感谢所有 – user704006 2011-04-15 14:13:00

0

请注意,您在每次迭代中创建新实例EntityManagerFactory,但不要关闭它。也许它会更好地使用一个工厂,而不是:

int counter = 0; 
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("MyPU");  
while (counter >= 0) { 
    javax.persistence.EntityManager em = emf.createEntityManager(); 
    ... 
} 
+0

我试图按照您的建议实施,但仍然没有释放内存。 – user704006 2011-04-15 10:54:29