2013-08-29 95 views
3

首先,有一點背景。我正在致力於從SQL Server中提取數據的管理軟件。我正在使用JPA來創建Entity表的實例,以便在管理軟件中進行操作(我現在只用了JPA幾天)。作爲測試,我將以下代碼放在一起,以測試將存儲多少內存用於存儲其最豐富表(PeriodicalTable)的對象,該對象具有18,500行(或約有),並且僅可能增長;JPA內存管理問題

public static void main(String[] args) { 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceDemoPU"); 
    EntityManager em = emf.createEntityManager(); 

    Query query = em.createQuery("SELECT p FROM PeriodicalTable p"); 
    //query.setMaxResults(7000); 
    List<PeriodicalTable> results = query.getResultList(); 
    PeriodicalTable storedPlayer; 

    for (int i = 0; i < results.size(); i++){ 
     storedPlayer = results.get(i); 
     System.out.println(storedPlayer.toString()); 
     if (i == (results.size()-1)){System.out.println("Total results: "+(i+1)); } 
    } 

    em.close(); 
    emf.close(); 
} 

上面的代碼拋出,即使我提出-Xmx到512M java.lang.OutOfMemoryError: Java heap space。我不想使用更多的內存,因爲這個軟件運行的電腦只有大約2GB的內存。現在,我可以對每個查詢使用.setMaxResults()(正如您可以看到的註釋),但這並不理想,因爲我需要在最終產品中顯示所有這些查詢。

所以,這個問題。在使用JPA的同時,是否還有更多的內存高效的方法在表中的每個實體上運行toString?這些不同方法的優缺點是什麼?我曾考慮過可能只存儲了一個由.toString()傳遞的字符串值列表,但是如果沒有先使用.getResultList()並將結果存儲在列表中,則無法想到這樣做的方式。

編輯:作爲一方,我使用Java Standard JPA,並沒有研究Hibernate或ObjectDB或類似的東西。除非他們的使用是必不可少的,我打算避免學習更多的技術。

+0

您可以請您爲PeriodicalTable顯示您的toString()實現。 –

+1

可能幫助 - 逐頁閱讀:http://java-persistence-performance.blogspot.com/2011/06/how-to-improve-jpa-performance-by-1825.html –

+0

@Rob Blake - 'public String toString(){返回引用;}引用只是一個字符串。 –

回答

3

您可以嘗試使用query.setMaxResults()query.setFirstResult()對結果進行分頁。這樣,您可以將結果加載到例如2500行的塊中。

+0

做'.setFirstResult()'使用行號還是主ID?這個表的主要ID都是在這個地方(我自己沒有設置它)。 –

+0

你能以任何獨特的方式訂購結果嗎?這樣做,它會工作得很好。 – Kayaman

+0

那麼主要的ID是唯一的,但是有很多的差距,但是在數字之間跳躍,不同長度的數字等等等等。我認爲這很好,它只會使任何邏輯難以定位。 –

2

一般來說,ORM不適合加載和處理大量數據。無論您的實施效率如何,ORM都會使用如此多的內存和CPU,因爲它們高度依賴反思。正如你在他們的文檔中可以看到的那樣,它們被設計用於加載 - 修改 - 持續方案。如果你需要加載和顯示大量的數據,你肯定會需要分頁。

0

請檢查PeriodicalTable映射和延遲加載對象。

+0

我到目前爲止的實體類沒有關聯的實體對象要獲取。如果這就是你的意思。否則恐怕我需要對您的答案進行一些澄清。 –