[Java][JPA] JPA で大きなテーブルを走査する
JPA で行数の多いテーブルを select して getResultList() すると全部メモリに展開するので効率が良くないです。こういうとき、JDBC なら ResultSet をオープンしたままループしますし、S2JDBC なら iterate() 使いますね。ところが JPA には適切な方法がないようです。
プロダクト独自の方法を使えばいいようですが、pure JPA なベストアンサーの方法を Iterator でラップして使いやすくしてみました。
https://github.com/akr4/jpa-lazy-fetch-iterator
こんな感じで Iterable として返してやると便利でしょう。
public Iterable<Employee> getAllEmployees() { return new Iterable<Employee>() { @Override public Iterator<Employee> iterator() { return new LazyFetchIterator<Employee>( em, em.createQuery("select e from Employee e order by e.id", Employee.class), em.createQuery("select count(e) from Employee e", Long.class).getSingleResult(), 1000); } }; }
第2引数の Query を使って 1000 件ずつフェッチします。
これくらいは JPA で提供してほしいなあ。