JPA:迭代大型结果集的正确模式是什么? [英] JPA: what is the proper pattern for iterating over large result sets?

查看:145
本文介绍了JPA:迭代大型结果集的正确模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一张有数百万行的表格。使用JPA,对该表执行迭代的正确方法是什么?我没有包含数百万个对象的所有内存列表



例如,如果表格很大,我怀疑以下情况会爆炸:

  List< Model> ; models = entityManager()。createQuery(from Model m,Model.class).getResultList(); (模型模型:模型)


{
System.out.println(model.getId());



$ b

是分页(循环和手动更新 setFirstResult() / setMaxResult())真的是最好的解决方案吗?

/ strong>:我要定位的主要用例是一种批处理作业。如果需要很长时间才能运行,这很好。没有涉及Web客户端;我只需要为每一行做点什么,一次一个(或者一些小N)。

http://rads.stackoverflow.com/amzn/click/1932394885\">使用Hibernate的Java持久化给出了一个使用 ScrollableResults 的解决方案,但是它只适用于Hibernate 。因此,看来使用 setFirstResult / setMaxResults 和手动迭代确实是必要的。这是我使用JPA的解决方案:

  private List< Model> getAllModelsIterable(int offset,int max)
{
return entityManager.createQuery(from Model m,Model.class).setFirstResult(offset).setMaxResults(max).getResultList();
}

然后,像这样使用它:

  private void iterateAll()
{
int offset = 0;

列表< Model>楷模; ((models = Model.getAllModelsIterable(offset,100))。size()> 0)
{
entityManager.getTransaction()。begin(); (模型:模型)

{
log.info(用模型做某事:+ model.getId());
}

entityManager.flush();
entityManager.clear();
em.getTransaction()。commit();
offset + = models.size();
}
}


Let's say I have a table with millions of rows. Using JPA, what's the proper way to iterate over a query against that table, such that I don't have all an in-memory List with millions of objects?

For example, I suspect that the following will blow up if the table is large:

List<Model> models = entityManager().createQuery("from Model m", Model.class).getResultList();

for (Model model : models)
{
     System.out.println(model.getId());
}

Is pagination (looping and manually updating setFirstResult()/setMaxResult()) really the best solution?

Edit: the primary use-case I'm targeting is a kind of batch job. It's fine if it takes a long time to run. There is no web client involved; I just need to "do something" for each row, one (or some small N) at a time. I'm just trying to avoid having them all in memory at the same time.

解决方案

Page 537 of Java Persistence with Hibernate gives a solution using ScrollableResults, but alas it's only for Hibernate.

So it seems that using setFirstResult/setMaxResults and manual iteration really is necessary. Here's my solution using JPA:

private List<Model> getAllModelsIterable(int offset, int max)
{
    return entityManager.createQuery("from Model m", Model.class).setFirstResult(offset).setMaxResults(max).getResultList();
}

then, use it like this:

private void iterateAll()
{
    int offset = 0;

    List<Model> models;
    while ((models = Model.getAllModelsIterable(offset, 100)).size() > 0)
    {
        entityManager.getTransaction().begin();
        for (Model model : models)
        {
            log.info("do something with model: " + model.getId());
        }

        entityManager.flush();
        entityManager.clear();
        em.getTransaction().commit();
        offset += models.size();
    }
}

这篇关于JPA:迭代大型结果集的正确模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆