diff --git a/documentation/src/main/asciidoc/introduction/Interacting.adoc b/documentation/src/main/asciidoc/introduction/Interacting.adoc index 365dbe73f5..e15f9ae16d 100644 --- a/documentation/src/main/asciidoc/introduction/Interacting.adoc +++ b/documentation/src/main/asciidoc/introduction/Interacting.adoc @@ -803,9 +803,13 @@ List books = .getResultList() ---- +[TIP] +==== +You can call stored procedures using `createStoredProcedureQuery()` or `createStoredProcedureCall()`. +==== [[pagination]] -=== Limits and pagination +=== Limits, pagination, and ordering If a query might return more results than we can handle at one time, we may specify: @@ -828,7 +832,7 @@ For example, this: [source,java] ---- List books = - session.createSelectionQuery("from Book where title like ?1") + session.createSelectionQuery("from Book where title like ?1 order by title") .setParameter(1, titlePattern) .setMaxResults(10) .getResultList(); @@ -839,12 +843,41 @@ is simpler than: [source,java] ---- List books = - session.createSelectionQuery("from Book where title like ?1 fetch first ?2 rows only") + session.createSelectionQuery("from Book where title like ?1 order by title fetch first ?2 rows only") .setParameter(1, titlePattern) .setParameter(2, 10) .getResultList(); ---- +A closely-related issue is ordering. +It's quite common for pagination to be combined with the need to order query results by a field that's determined at runtime. +So, as an alternative to the HQL `order by` clause, Hibernate's `SelectionQuery` interface offers the ability to specify that the query results should be ordered by one or more fields of the entity type returned by the query: + +[source,java] +---- +List books = + session.createSelectionQuery("from Book where title like ?1") + .setParameter(1, titlePattern) + .ascending(Book._title) + .ascending(Book._isbn) + .setMaxResults(10) + .getResultList(); +---- + +Unfortunately, there's no way to do this using JPA's `TypedQuery` interface. + +.Methods for query limits, pagination, and ordering +[%breakable,cols="30,~,^15"] +|=== +| Method name | Purpose | JPA-standard + +| `setMaxResults()` | Set a limit on the number of results returned by a query | ✔ +| `setFirstResult()` | Set an offset on the results returned by a query | ✔ +| `ascending()` | Add a field to use to order the results | ✖ +| `descending()` | Add a field to use to order the results | ✖ +| `unordered()` | Clear any current ordering | ✖ +|=== + [[projection-lists]] === Representing projection lists @@ -942,7 +975,7 @@ There's much less advantage to using `@NamedNativeQuery`, because there is very | Mutation | `createNamedMutationQuery(String)` | `createNamedQuery(String)` | `executeUpdate()` |=== -We execute our named query as follows: +We execute our named query like this: [source,java] ---- @@ -952,7 +985,7 @@ List books = .getResultList() ---- -Here, `BookQueries_.QUERY_10_BOOKS_BY_TITLE` is generated by the Metamodel Generator, and is just a constant with the value `"10BooksByTitle"`. +Here, `BookQueries_.QUERY_10_BOOKS_BY_TITLE` is a constant with value `"10BooksByTitle"`, generated by the Metamodel Generator. Note that the code which executes the named query is not aware of whether the query was written in HQL or in native SQL, making it slightly easier to change and optimize the query later. @@ -1037,11 +1070,6 @@ session.doWork(connection -> { The `Connection` passed to the work is the same connection being used by the session, and so any work performed using that connection occurs in the same transaction context. -[TIP] -==== -You can call stored procedures using `createStoredProcedureQuery()` or `createStoredProcedureCall()`. -==== - If the work returns a value, use `doReturningWork()` instead of `doWork()`. [[advice]]