大表的setMaxResults使用太多内存

时间:2014-11-20 23:54:44

标签: java hibernate postgresql jpa hql

我正在使用 Hibernate ,我想执行此查询:

SELECT s.executionTime, g.date, s.name
FROM SimulationStatsGroup g
LEFT JOIN SimulationStats s ON s.group_id = g.id
WHERE g.name = 'general'
ORDER BY g.date DESC
LIMIT 30

在此查询中,我必须使用表格,而SimulationStatsGroup包含多个SimulationStats

但是,对于 HQL LIMIT会生成错误,因为 hibernate 不支持它。 所以我使用了setMaxResults(int),但是当我在日志中查找查询时,我发现根本没有LIMIT

这可能是因为 Hibernate 知道SimulationStatsGroup可以包含多个SimulationStats,因此它知道限制为30个结果将不会返回30 SimulationStatsGroup如果我们假设1 SimulationStatsGroup中有10 SimulationStats,那么我只需要30行,这会给我3 SimulationStatsGroup

所以,我可以理解为什么它以这种方式工作而不是我想要的方式。但是,这种执行查询的方式使我的应用程序崩溃,因为它占用了太多内存,因为我的表中有超过100万行,而且似乎 Hibernate 试图将所有行放入列表。

我的问题是:有没有办法限制使用内存来保持我的应用程序活着并只保留我的30个对象?

1 个答案:

答案 0 :(得分:2)

对于非常大的表,我建议您使用the seek method,但它需要运行本机查询,并且每个数据库都有自己的限制行号的方法。

在您的情况下,您只需运行两个查询而不是一个:

  • 第一个查询只返回父ID:

    Session session = sessionFactory.openSession();
    Query query = session.createQuery("select ssg.id from SimulationStatsGroup ssg");
    query.setFirstResult(0);
    query.setMaxResults(10);
    List<Long> ids = query.list();
    
  • 然后您可以使用第二个查询来获取包含子项的父项:

    Session session = sessionFactory.openSession();
    Query query = session.createQuery("select ssg from SimulationStatsGroup ssg left join fetch ssg.simulationStats where ssg.id in (:ids) ");
    query.setParameterList("ids", ids);
    List<SimulationStatsGroup> simulationStatsGroups = query.list();
    

这样您就可以绕过Hibernate内存中的Parent-Child分组限制。