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.