首先,一点背景。我正在研究从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等等。除非他们的使用是必不可少的,否则我打算避免学习更多的技术而不是必要的。
答案 0 :(得分:3)
您可以尝试使用query.setMaxResults()
和query.setFirstResult()
对结果进行分页。这样,您可以将结果加载到例如2500行的块中。
答案 1 :(得分:2)
一般来说,ORM不适合加载和处理大量数据。无论您的实现效率如何,ORM都将使用如此多的内存和CPU,因为它们高度依赖于反射。正如您在其文档中看到的那样,它们是为Load-Modify-Persist场景设计的。如果您需要加载并显示大量数据,您肯定需要分页。
答案 2 :(得分:0)
请检查PeriodicalTable映射和延迟加载对象。