2011-04-15 61 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