假设我有一个包含数百万行的表。使用JPA,迭代对该表的查询的正确方法是什么,以至于 我没有一个 包含数百万个对象 的内存列表 ?
例如,如果表很大,我怀疑以下内容会爆炸:
List<Model> models = entityManager().createQuery("from Model m", Model.class).getResultList(); for (Model model : models) { System.out.println(model.getId()); }
分页(循环和手动更新setFirstResult()/ setMaxResult())真的是最好的解决方案吗?
setFirstResult()
setMaxResult()
编辑 :我针对的主要用例是一种批处理作业。如果需要很长时间才能运行就可以了。没有涉及Web客户端。我只需要为每一行“做某事”,一次一行(或一些小N)。我只是想避免将它们全部同时存储在内存中。
Java Persistence with Hibernate的第537页提供了一个使用的解决方案ScrollableResults,但可惜它仅适用于Hibernate。
ScrollableResults
因此,似乎需要使用setFirstResult/ setMaxResults和手动迭代。这是我使用JPA的解决方案:
setFirstResult
setMaxResults
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; 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(); } }