JPA内存管理问题

时间:2013-08-29 10:18:45

标签: java sql jpa memory-management persistence

首先,一点背景。我正在研究从SQL Server中提取数据的管理软件。我正在使用JPA来创建表的Entity个实例,以便在管理软件中进行操作(我现在只使用JPA几天了)。作为一个测试,我将下面的代码汇总在一起,以测试存储多少内存将占用最丰富的表(PeriodicalTable)的对象,这些表有18,500行(或大约有)并且只能增长;

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();   
}

上面的代码抛出java.lang.OutOfMemoryError: Java heap space,即使我已经将-Xmx提升到512m。我不想再使用内存,因为这个软件运行的计算机只有大约2GB的RAM。现在,我可以对每个查询使用.setMaxResults()(正如您所看到的那样),但这并不理想,因为我需要在最终产品中显示所有这些查询。

所以,问题。是否有更多内存有效的方法在表中的每个实体上运行toString,同时使用JPA?这些不同方法的优点和缺点是什么?我曾想过可能只存储.toString()传递的字符串值列表,但如果没有先使用.getResultList()并将结果存储在列表中,就无法想到这样做的方法。

编辑:作为一方,我使用的是Java Standard JPA,并没有考虑过Hibernate或ObjectDB等等。除非他们的使用是必不可少的,否则我打算避免学习更多的技术而不是必要的。

3 个答案:

答案 0 :(得分:3)

您可以尝试使用query.setMaxResults()query.setFirstResult()对结果进行分页。这样,您可以将结果加载到例如2500行的块中。

答案 1 :(得分:2)

一般来说,ORM不适合加载和处理大量数据。无论您的实现效率如何,ORM都将使用如此多的内存和CPU,因为它们高度依赖于反射。正如您在其文档中看到的那样,它们是为Load-Modify-Persist场景设计的。如果您需要加载并显示大量数据,您肯定需要分页。

答案 2 :(得分:0)

请检查PeriodicalTable映射和延迟加载对象。