`try ( ScrollableResults scrollableResults = session.createQuery(
15.4.1. Query scrolling
<div class="paragraph">
Hibernate offers additional, specialized methods for scrolling the query and handling results using a server-side cursor.
</div>
<div class="paragraph">
`Query#scroll` works in tandem with the JDBC notion of a scrollable `ResultSet`.
</div>
<div class="paragraph">
The `Query#scroll` method is overloaded:
</div>
<div class="ulist">
- Then main form accepts a single argument of type
org.hibernate.ScrollModewhich indicates the type of scrolling to be used. See the Javadocs for the details on each. The second form takes no argument and will use the
ScrollModeindicated byDialect#defaultScrollMode. </div>Query#scrollreturns aorg.hibernate.ScrollableResultswhich wraps the underlying JDBC (scrollable)ResultSetand provides access to the results. Unlike a typical forward-onlyResultSet, theScrollableResultsallows you to navigate theResultSetin any direction.</div>
Example 361. Scrolling through a `ResultSet` containing entities"select p " + "from Person p " + "where p.name like :name" ) .setParameter( "name", "J%" ) .scroll()) {
while(scrollableResults.next()) { Person person = (Person) scrollableResults.get()[0]; process(person); }}`</pre> </div> </div> </div> </div>
</td>
Since this form holds the JDBC
ResultSetopen, the application should indicate when it is done with theScrollableResultsby calling itsclose()method (as inherited fromjava.io.Closeableso thatScrollableResultswill work with try-with-resources blocks).</div>
If left unclosed by the application, Hibernate will automatically close the underlying resources (e.g.
ResultSetandPreparedStatement) used internally by theScrollableResultswhen the current transaction is ended (either commit or rollback).</div>
However, it is good practice to close the
ScrollableResultsexplicitly.</div> </td> </tr> </table> </div>
</td>
If you plan to use
Query#scrollwith collection fetches it is important that your query explicitly order the results so that the JDBC results contain the related rows sequentially.</div> </td> </tr> </table> </div>
Hibernate also supports
Query#iterate, which is intended for loading entities when it is known that the loaded entries are already stored in the second-level cache. The idea behind iterate is that just the matching identifiers will be obtained in the SQL query. From these the identifiers are resolved by second-level cache lookup. If these second-level cache lookups fail, additional queries will need to be issued against the database.</div>
</td>
This operation can perform significantly better for loading large numbers of entities that for certain already exist in the second-level cache. In cases where many of the entities do not exist in the second-level cache, this operation will almost definitely perform worse.
</div> </td> </tr> </table> </div>
The
Iteratorreturned fromQuery#iterateis actually a specially typed Iterator:org.hibernate.engine.HibernateIterator. It is specialized to expose aclose()method (again, inherited fromjava.io.Closeable). When you are done with thisIteratoryou should close it, either by casting toHibernateIteratororCloseable, or by callingHibernate#close(java.util.Iterator).</div>
Since 5.2, Hibernate offers support for returning a
Streamwhich can be later used to transform the underlyingResultSet.</div>
Internally, the
stream()behaves like aQuery#scrolland the underlying result is backed by aScrollableResults.</div>
Fetching a projection using the
Query#streammethod can be done as follows:</div>
Example 362. Hibernate `stream()` using a projection result type`try ( Stream<Object[]> persons = session.createQuery(
"select p.name, p.nickName " + "from Person p " + "where p.name like :name" ).setParameter( "name", "J%" ) .stream() ) {
persons .map( row -> new PersonNames( (String) row[0], (String) row[1] ) ) .forEach( this::process );}`</pre> </div> </div> </div> </div>
When fetching a single result, like a
Personentity, instead of aStream<Object[]>, Hibernate is going to figure out the actual type, so the result is aStream<Person>.</div>
Example 363. Hibernate `stream()` using an entity result type`try( Stream<Person> persons = session.createQuery(
"select p " + "from Person p " + "where p.name like :name" ).setParameter( "name", "J%" ) .stream() ) {
Map<Phone, List<Call>> callRegistry = persons .flatMap( person -> person.getPhones().stream() ) .flatMap( phone -> phone.getCalls().stream() ) .collect( Collectors.groupingBy( Call::getPhone ) ); process(callRegistry);}`</pre> </div> </div> </div> </div>
</td>
Just like with
ScrollableResults, you should always close a HibernateStreameither explicitly or using a try-with-resources block.</div> </td> </tr> </table> </div> </div> </div>