2013-08-29 171 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

我到目前为止的实体类没有关联的实体对象要获取。如果这就是你的意思。否则恐怕我需要对您的答案进行一些澄清。 –