Supposing you have to fetch a large resultset and update the single objects. By using the standard Query Object you would retrieve the whole set of Objects in Memory:
Query q = session.createQuery("from ABC"); List l = q.list();
On the other hand, if you need to operate on an online cursor, then you can use the ScrollableResults in your Query as you can see in this example:
public class ScrollableResultsWithQuery { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); ScrollableResults scResults = session.createQuery("from Customer") .scroll(ScrollMode.SCROLL_INSENSITIVE); while(scResults.next()) { Customer c = (Customer)scResults.get(0); System.out.println(g.getId()+", "+g.getName()); scResults.afterLast(); } session.close(); } }
ScrollableResults requires the underlying Hibernate API for the scrolling but you can use all the features of JPA querying.
There are different modes available in ScrollableResults:
FORWARD_ONLY : It requests ScrollableResults that scrolls forward only.
SCROLL_SENSITIVE : ScrollableResults that is sensitive to changes in underlying data.
SCROLL_INSENSITIVE : Insensitive to changes in underlying data.
You are not restricted to using ScrollableResults with Query, you can use it also with the Criteria API:
public class ScrollableResultsWithCriteria { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); ScrollableResults scResults = session.createCriteria(Customer.class) .scroll(ScrollMode.FORWARD_ONLY); while(scResults.next()) { Customer c = (Customer)scResults.get(0); System.out.println(c.getId()+", "+c.getName()); } //Set the location at index 2 System.out.println("After setting location"); scResults.setRowNumber(1); while(scResults.next()) { Customer c = (Customer)scResults.get(0); System.out.println(c.getId()+", "+c.getName()); } session.close(); } }
Scrolling in JPA
There is no equivalent API in JPA to scroll through an open cursor. Still you can use as alternative the methods setMaxResult()/setFirstResult() as discussed in this tutorial: How to paginate your Entity data
Query query = em.createQuery("From Account"); query.setFirstResult(0); query.setMaxResults(10); List<Account> list = query.list();
In terms of performance, however, consider that using setMaxResult()/setFirstResult() will fire a new query every time, and the overhead really adds up. Plus, you need to sort on something for reliable paging which also adds to query times.