Skip to content

Commit 781cdc8

Browse files
committed
more improvements to the new chapter
1 parent ae2f73a commit 781cdc8

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

documentation/src/main/asciidoc/introduction/Generator.adoc

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,13 @@ For example, you could use it to create your own criteria query API.
115115
Automatic generation of _finder methods_ and _query methods_ is a new feature of Hibernate's implementation of the Metamodel Generator, and an extension to the functionality defined by the JPA specification.
116116
In this chapter, we're going to explore these features.
117117

118-
To whet our appetites, let's see how it works for a `@NamedQuery`.
118+
We're going to meet three different kinds of generated method:
119+
120+
- a _named query method_ has its signature and implementation generated directly from a `@NamedQuery` annotation,
121+
- a _query method_ has a signature that's explicitly declared, and a generated implementation which executes a HQL or SQL query specified via a `@HQL` or `@SQL` annotation, and
122+
- a _finder method_ annotated `@Find` has a signature that's explicitly declared, and a generated implementation inferred from the parameter list.
123+
124+
To whet our appetites, let's see how this works for a `@NamedQuery`.
119125

120126
[[generated-named-queries]]
121127
=== Named queries and the Metamodel Generator
@@ -128,9 +134,7 @@ Let's just stick it on the `Book` class:
128134
----
129135
@CheckHQL // validate the query at compile time
130136
@NamedQuery(name = "#findByTitleAndType",
131-
query = "select book from Book book " +
132-
"where book.title like :titlePattern " +
133-
" and book.type = :type")
137+
query = "select book from Book book where book.title like :titlen and book.type = :type")
134138
@Entity
135139
public class Book { ... }
136140
----
@@ -141,11 +145,11 @@ Now the Metamodel Generator adds the following method declaration to the metamod
141145
.Generated Code
142146
----
143147
/**
144-
* Executes named query {@value #QUERY_FIND_BY_TITLE_AND_TYPE} defined by annotation of {@link Book}.
148+
* Execute named query {@value #QUERY_FIND_BY_TITLE_AND_TYPE} defined by annotation of {@link Book}.
145149
**/
146-
public static List<Book> findByTitleAndType(EntityManager entityManager, String titlePattern, Type type) {
150+
public static List<Book> findByTitleAndType(@Nonnull EntityManager entityManager, String title, Type type) {
147151
return entityManager.createNamedQuery(QUERY_FIND_BY_TITLE_AND_TYPE)
148-
.setParameter("titlePattern", titlePattern)
152+
.setParameter("titlePattern", title)
149153
.setParameter("type", type)
150154
.getResultList();
151155
}
@@ -164,8 +168,8 @@ Now, this is quite nice, but it's a bit inflexible in various ways, and so this
164168
[[generated-query-methods]]
165169
=== Generated query methods
166170

167-
The problem with generating the query method straight from the `@NamedQuery` annotation is that it doesn't let us explicitly specify the return type or parameter list.
168-
The Metamodel Generator does a good job of inferring the query return type and parameter types, but we're often going to need a bit more control.
171+
The principal problem with generating the query method straight from the `@NamedQuery` annotation is that it doesn't let us explicitly specify the return type or parameter list.
172+
In the case we just saw, the Metamodel Generator does a reasonable job of inferring the query return type and parameter types, but we're often going to need a bit more control.
169173

170174
The solution is to write down the signature of the query method _explicitly_, as an abstract method in Java.
171175
We'll need a place to put this method, and since our `Book` entity isn't an abstract class, we'll just introduce a new interface for this purpose:
@@ -179,7 +183,6 @@ interface Queries {
179183
----
180184

181185
Instead of `@NamedQuery`, which is a type-level annotation, we specify the HQL query using the new `@HQL` annotation, which we place directly on the query method.
182-
183186
This results in the following generated code in the `Queries_` class:
184187

185188
[source,java]
@@ -209,6 +212,23 @@ public abstract class Queries_ {
209212

210213
Notice that the signature differs just slightly from the one we wrote down in the `Queries` interface: the Metamodel Generator has prepended a parameter accepting `EntityManager` to the parameter list.
211214

215+
If we want to explicitly specify the name and type of this parameter, we may declare it explicitly:
216+
217+
[source,java]
218+
----
219+
interface Queries {
220+
@HQL("from Book where title like :title and type = :type")
221+
List<Book> findBooksByTitleAndType(StatelessSession session, String title, String type);
222+
}
223+
----
224+
225+
The Metamodel Generator defaults to using `EntityManager` as the session type, but other types are allowed:
226+
227+
- `Session`,
228+
- `StatelessSession`, or
229+
- `Mutiny.Session` from Hibernate Reactive.
230+
231+
The real value of all this is in the checks which can now be done at compile time.
212232
The Metamodel Generator verifies that the parameters of our abstract method declaration match the parameters of the HQL query, for example:
213233

214234
- for a named parameter `:alice`, there must be a method parameter named `alice` with exactly the same type, or
@@ -237,6 +257,7 @@ But if this function is called from many places, it's probably better to promote
237257
Fortunately, this is straightforward.
238258

239259
All we need to do is add an abstract getter method for the session object to our `Queries` interface.
260+
(And remove the session from the method parameter list.)
240261
We may call this method anything we like:
241262

242263
[source,java]
@@ -249,11 +270,7 @@ interface Queries {
249270
}
250271
----
251272

252-
Here we've used `EntityManager` as the session type, but other types are allowed:
253-
254-
- `Session`,
255-
- `StatelessSession`, or
256-
- `Mutiny.Session` from Hibernate Reactive.
273+
Here we've used `EntityManager` as the session type, but other types are allowed, as we saw above.
257274

258275
Now the Metamodel Generator does something a bit different:
259276

0 commit comments

Comments
 (0)