Skip to content

Commit 3e0568a

Browse files
committed
update chapter on Hibernate Processor for H7
Signed-off-by: Gavin King <[email protected]>
1 parent 7bd50db commit 3e0568a

File tree

5 files changed

+51
-40
lines changed

5 files changed

+51
-40
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class User {
6666
}
6767
----
6868

69-
Here, as usual, `example_.BY_REGION` is generated by the Metamodel Generator, and is just a constant with the value `"ByRegion"`.
69+
Here, as usual, `example_.BY_REGION` is generated by Hibernate Processor, and is just a constant with the value `"ByRegion"`.
7070

7171
If the `@Filter` annotation does not explicitly specify a restriction, the default restriction given by the `@FilterDef` will be applied to the entity.
7272
But an entity is free to override the default condition.
@@ -1081,7 +1081,7 @@ class Author {
10811081
}
10821082
----
10831083

1084-
Here, once again, `Book_.PROFILE_EAGER_BOOK` is generated by the Metamodel Generator, and is just a constant with the value `"EagerBook"`.
1084+
Here, once again, `Book_.PROFILE_EAGER_BOOK` is generated by Hibernate Processor, and is just a constant with the value `"EagerBook"`.
10851085

10861086
For collections, we may even request subselect fetching:
10871087

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,8 +1018,8 @@ class Publisher {
10181018
The `Publisher.books` field is called the _unowned_ side of the association.
10191019

10201020
Now, we passionately _hate_ the stringly-typed `mappedBy` reference to the owning side of the association.
1021-
Thankfully, the <<metamodel-generator, Metamodel Generator>> gives us a way to make it a
1022-
bit more typesafe:
1021+
Thankfully, the <<metamodel-generator, Hibernate Processor>> gives us a way to make it a
1022+
bit more type safe:
10231023

10241024
[[mapped-by-metamodel]]
10251025
[source,java]

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

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
[[generator]]
22
== Compile-time tooling
33

4-
The Metamodel Generator is a standard part of JPA.
4+
The _static metamodel generator_ is a standard part of JPA.
55
// It's an annotation processor that produces a statically-typed metamodel of the entity classes in a Java program.
6-
We've actually already seen its handiwork in the code examples <<main-jpa,earlier>>: it's the author of the class `Book_`, which contains the static metamodel of the <<book,entity class>> `Book`.
6+
We've actually already seen its handiwork in the code examples <<main-hibernate,earlier>>: it's the author of the class `Book_`, which contains the static metamodel of the <<book,entity class>> `Book`.
77

88
[[metamodel-generator]]
9-
.The Metamodel Generator
9+
.Hibernate Processor
1010
****
1111
1212
:generator: https://hibernate.org/orm/tooling/
1313
:generator-guide: {doc-user-guide-url}#tooling-modelgen
1414
15-
Hibernate's {generator}[Metamodel Generator] is an annotation processor that produces what JPA calls a _static metamodel_.
16-
That is, it produces a typed model of the persistent classes in our program, giving us a type-safe way to refer to their attributes in Java code.
15+
{generator}[Hibernate Processor], the annotation processor formerly known as the Metamodel Generator, began its life as a code generator for what JPA calls a _static metamodel_.
16+
That is, it produces a typed model of the persistent classes in our program, giving us a type safe way to refer to their attributes in Java code.
1717
In particular, it lets us specify <<entity-graph,entity graphs>> and <<criteria-queries,criteria queries>> in a completely type-safe way.
1818
1919
The history behind this thing is quite interesting.
@@ -25,20 +25,21 @@ And all the explicit generic types made user code quite verbose and difficult to
2525
For years, Gavin counted this as one of his more embarrassing missteps.
2626
2727
But time has been kind to the static metamodel.
28-
In 2023, all Java compilers, build tools, and IDEs have robust support for annotation processing, and Java's local type inference (the `var` keyword) eliminates the verbose generic types.
28+
By now, all Java compilers, build tools, and IDEs have robust support for annotation processing, and Java's local type inference (the `var` keyword) eliminates the verbose generic types.
2929
JPA's `CriteriaBuilder` and `EntityGraph` APIs are still not quite perfect, but the imperfections aren't related to static type safety or annotation processing.
3030
The static metamodel itself is undeniably useful and elegant.
3131
32-
And so now, in Hibernate 6.3, we're finally ready to go new places with the Metamodel Generator.
33-
And it turns out that there's quite a lot of unlocked potential there.
32+
And it turns out that there was quite a lot of unlocked potential there.
33+
Since Hibernate 6.3 the Processor has started taking on a much bigger role.
34+
Today, it even contains a complete implementation of the Jakarta Data specification.
3435
35-
Now, you still don't have to use the Metamodel Generator with Hibernate—the APIs we just mentioned still also accept plain strings—but we find that it works well with Gradle and integrates smoothly with our IDE, and the advantage in type-safety is compelling.
36+
Now, you still don't have to use the Hibernate Processor with Hibernate—the APIs we just mentioned still also accept plain strings—but we find that it works well with Gradle and integrates smoothly with our IDE, and the advantage in type-safety is compelling.
3637
****
3738

3839
[TIP]
3940
====
4041
We've already seen how to set up the annotation processor in the <<hello-hibernate,Gradle build>> we saw earlier.
41-
For more details on how to integrate the Metamodel Generator, check out the {generator-guide}[Static Metamodel Generator] section in the User Guide.
42+
For more details on how to integrate the Hibernate Processor, check out the {generator-guide}[Static Metamodel Generator] section in the User Guide.
4243
====
4344

4445
Here's an example of the sort of code that's generated for an entity class, as mandated by the JPA specification:
@@ -100,12 +101,9 @@ For each attribute of the entity, the `Book_` class has:
100101
1. a `String`-valued constant like `TITLE` , and
101102
2. a typesafe reference like `title` to a metamodel object of type `Attribute`.
102103

103-
We've already been using metamodel references like `Book_.authors` and `Book.AUTHORS` in the previous chapters.
104-
So now let's see what else the Metamodel Generator can do for us.
105-
106104
[TIP]
107105
====
108-
The Metamodel Generator provides _statically-typed_ access to elements of the JPA `Metamodel`. But the `Metamodel` is also accessible in a "reflective" way, via the `EntityManagerFactory`.
106+
Hibernate Processor allows _statically-typed_ access to elements of the JPA `Metamodel`. But the `Metamodel` is also accessible in a "reflective" way, via the `EntityManagerFactory`.
109107
110108
[source,java]
111109
----
@@ -118,16 +116,21 @@ This is very useful for writing generic code in frameworks or libraries.
118116
For example, you could use it to create your own criteria query API.
119117
====
120118

121-
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.
122-
In this chapter, we're going to explore these features.
119+
We've already been using metamodel references like `Book_.authors` and `Book.AUTHORS` in the previous chapters.
120+
So now let's see what else Hibernate Processor can do for us.
123121

124-
[CAUTION]
122+
[NOTE]
125123
====
126-
The functionality described in the rest of this chapter depends on the use of the annotations described in <<entities>>.
127-
The Metamodel Generator is not currently able to generate finder methods and query methods for entities declared completely in XML, and it's not able to validate HQL which queries such entities.
128-
(On the other hand, the <<object-relational-mapping,O/R mappings>> may be specified in XML, since they're not needed by the Metamodel Generator.)
124+
The functionality we're about to describe was developed before Jakarta Data took on its current shape, and directly triggered the apocalypse which lead to the final form of the specification.
125+
Therefore, there's massive overlap between the functionality described in this chapter, and the functionality available via the Jakarta Data annotations.
126+
On the other hand, Jakarta Data can't do _everything_ described below, and in particular it doesn't yet come with built-in support for stateful persistence contexts or reactive sessions.
127+
128+
We've therefore opted _not_ to rewrite this chapter in a Jakarta Data-centric way, and instead refer you to link:{doc-data-repositories-url}[Introducing Hibernate Data Repositories].
129129
====
130130

131+
Automatic generation of _finder methods_ and _query methods_ is a relatively new feature of Hibernate Processor, and an extension to the functionality defined by the JPA specification.
132+
In this chapter, we're going to explore these features.
133+
131134
We're going to meet three different kinds of generated method:
132135

133136
- a _<<generated-named-queries,named query method>>_ has its signature and implementation generated directly from a `@NamedQuery` annotation,
@@ -141,8 +144,15 @@ We're also going to see two ways that these methods can be called:
141144

142145
To whet our appetites, let's see how this works for a `@NamedQuery`.
143146

147+
[CAUTION]
148+
====
149+
The functionality described in the rest of this chapter depends on the use of the annotations described in <<entities>>.
150+
Hibernate Processor is not currently able to generate finder methods and query methods for entities declared completely in XML, and it's not able to validate HQL which queries such entities.
151+
(On the other hand, the <<object-relational-mapping,O/R mappings>> may be specified in XML, since they're not needed by the Processor.)
152+
====
153+
144154
[[generated-named-queries]]
145-
=== Named queries and the Metamodel Generator
155+
=== Named queries and Hibernate Processor
146156

147157
The very simplest way to generate a query method is to put a `@NamedQuery` annotation anywhere we like, with a `name` beginning with the magical character `#`.
148158

@@ -157,7 +167,7 @@ Let's just stick it on the `Book` class:
157167
public class Book { ... }
158168
----
159169

160-
Now the Metamodel Generator adds the following method declaration to the metamodel class `Book_`.
170+
Now the Processor adds the following method declaration to the metamodel class `Book_`.
161171

162172
[source,java]
163173
.Generated Code
@@ -187,7 +197,7 @@ Now, this is quite nice, but it's a bit inflexible in various ways, and so this
187197
=== Generated query methods
188198

189199
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.
190-
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.
200+
In the case we just saw, Hibernate Processor does a reasonable job of inferring the query return type and parameter types, but we're often going to need a bit more control.
191201

192202
The solution is to write down the signature of the query method _explicitly_, as an abstract method in Java.
193203
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:
@@ -228,7 +238,7 @@ public abstract class Queries_ {
228238
229239
----
230240

231-
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.
241+
Notice that the signature differs just slightly from the one we wrote down in the `Queries` interface: the Processor has prepended a parameter accepting `EntityManager` to the parameter list.
232242

233243
If we want to explicitly specify the name and type of this parameter, we may declare it explicitly:
234244

@@ -240,28 +250,28 @@ interface Queries {
240250
}
241251
----
242252

243-
The Metamodel Generator defaults to using `EntityManager` as the session type, but other types are allowed:
253+
Hibernate Processor defaults to using `EntityManager` as the session type, but other types are allowed:
244254

245255
- `Session`,
246256
- `StatelessSession`, or
247257
- `Mutiny.Session` from Hibernate Reactive.
248258

249259
The real value of all this is in the checks which can now be done at compile time.
250-
The Metamodel Generator verifies that the parameters of our abstract method declaration match the parameters of the HQL query, for example:
260+
Hibernate Processor verifies that the parameters of our abstract method declaration match the parameters of the HQL query, for example:
251261

252262
- for a named parameter `:alice`, there must be a method parameter named `alice` with exactly the same type, or
253263
- for an ordinal parameter `?2`, the second method parameter must have exactly the same type.
254264

255265
The query must also be syntactically legal and semantically well-typed, that is, the entities, attributes, and functions referenced in the query must actually exist and have compatible types.
256-
The Metamodel Generator determines this by inspecting the annotations of the entity classes at compile time.
266+
Hibernate Processor determines this by inspecting the annotations of the entity classes at compile time.
257267

258268
[NOTE]
259269
====
260270
The `@CheckHQL` annotation which instructs Hibernate to validate named queries is _not_ necessary for query methods annotated `@HQL`.
261271
====
262272

263273
The `@HQL` annotation has a friend named `@SQL` which lets us specify a query written in native SQL instead of in HQL.
264-
In this case there's a lot less the Metamodel Generator can do to check that the query is legal and well-typed.
274+
In this case there's a lot less the Processor can do to check that the query is legal and well-typed.
265275

266276
We imagine you're wondering whether a `static` method is really the right thing to use here.
267277

@@ -290,7 +300,7 @@ interface Queries {
290300

291301
Here we've used `EntityManager` as the session type, but other types are allowed, as we saw above.
292302

293-
Now the Metamodel Generator does something a bit different:
303+
Now Hibernate Processor does something a bit different:
294304

295305
[source,java]
296306
.Generated Code
@@ -750,5 +760,5 @@ The Query Validator works in `javac`, Gradle, Maven, and the Eclipse Java Compil
750760

751761
[CAUTION]
752762
====
753-
Unlike the Metamodel Generator, which is a completely bog-standard Java annotation processor based on only standard Java APIs, the Query Validator makes use of internal compiler APIs in `javac` and `ecj`. This means it can't be guaranteed to work in every Java compiler. The current release is known to work in JDK 11 and above, though JDK 15 or above is preferred.
763+
Unlike Hibernate Processor, which is a completely bog-standard Java annotation processor based on only standard Java APIs, the Query Validator makes use of internal compiler APIs in `javac` and `ecj`. This means it can't be guaranteed to work in every Java compiler. The current release is known to work in JDK 11 and above, though JDK 15 or above is preferred.
754764
====

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ This results in a SQL query with _four_ ``left outer join``s.
520520

521521
[NOTE]
522522
====
523-
In the code examples above, The classes `Book_` and `Author_` are generated by the <<metamodel-generator,JPA Metamodel Generator>> we saw earlier.
523+
In the code examples above, The classes `Book_` and `Author_` are generated by <<metamodel-generator,Hibernate Processor>>, as we saw earlier.
524524
They let us refer to attributes of our model in a completely type-safe way.
525525
We'll use them again, below, when we talk about <<criteria-queries>>.
526526
====
@@ -859,7 +859,7 @@ query.select(book).where(where)
859859
.orderBy(builder.asc(book.get(Book_.title)));
860860
----
861861

862-
Here, as before, the classes `Book_` and `Author_` are generated by Hibernate's <<metamodel-generator,JPA Metamodel Generator>>.
862+
Here, as before, the classes `Book_` and `Author_` are generated by <<metamodel-generator,Hibernate Processor>>.
863863

864864
[NOTE]
865865
// .Injection attacks and criteria queries
@@ -1270,7 +1270,7 @@ List<Book> books =
12701270
.getResultList()
12711271
----
12721272

1273-
Here, `BookQueries_.QUERY_10_BOOKS_BY_TITLE` is a constant with value `"10BooksByTitle"`, generated by the Metamodel Generator.
1273+
Here, `BookQueries_.QUERY_10_BOOKS_BY_TITLE` is a constant with value `"10BooksByTitle"`, generated by the Hibernate Processor.
12741274

12751275
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.
12761276

@@ -1280,7 +1280,7 @@ Note that the code which executes the named query is not aware of whether the qu
12801280
12811281
It's nice to have our queries checked at startup time.
12821282
It's even better to have them checked at compile time.
1283-
In <<organizing-persistence>>, we mentioned that the Metamodel Generator can do that for us, with the help of the `@CheckHQL` annotation, and we presented that as a reason to use `@NamedQuery`.
1283+
In <<organizing-persistence>>, we mentioned that the Hibernate Processor can do that for us, with the help of the `@CheckHQL` annotation, and we presented that as a reason to use `@NamedQuery`.
12841284
12851285
But actually, Hibernate has a separate <<query-validator,Query Validator>> capable of performing compile-time validation of HQL query strings that occur as arguments to `createQuery()` and friends.
12861286
If we use the Query Validator, there's not much advantage to the use of named queries.
@@ -1352,7 +1352,7 @@ Book book =
13521352
.load();
13531353
----
13541354

1355-
Notice that this code fragment is completely typesafe, again thanks to the <<metamodel-generator,Metamodel Generator>>.
1355+
Notice that this code fragment is completely typesafe, again thanks to <<metamodel-generator,Hibernate Processor>>.
13561356

13571357
[[jdbc]]
13581358
=== Interacting directly with JDBC

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ If you're new to Hibernate, frameworks which wrap JPA are quite likely to make y
430430
We prefer a _bottom-up_ approach to organizing our code.
431431
We like to start thinking about methods and functions, not about architectural layers and container-managed objects.
432432

433+
.Rethinking the persistence layer
433434
****
434435
When we wrote _An Introduction to Hibernate 6_, the predecessor of this document, we broke with a long practice of remaining agnostic in debates over application architecture.
435436
Into the vacuum created by our agnosticism had poured a wealth of advice which tended to encourage over-engineering and violation of the First Commandment of software engineering: _Don't Repeat Yourself._
@@ -638,7 +639,7 @@ Alternatively, if CDI isn't available, we may directly instantiate the generated
638639
The Jakarta Data specification now formalizes this approach using standard annotations, and our implementation of this specification, Hibernate Data Repositories, is built into Hibernate Processor.
639640
You probably already have it available in your program.
640641
641-
Unlike other repository frameworks, Hibernate Data Repositories offers something that plain JPA simply doesn’t have: full compile-time type safety for your queries. To learn more, please refer to _Introducing Hibernate Data Repositories._
642+
Unlike other repository frameworks, Hibernate Data Repositories offers something that plain JPA simply doesn’t have: full compile-time type safety for your queries. To learn more, please refer to link:{doc-data-repositories-url}[Introducing Hibernate Data Repositories].
642643
====
643644

644645
Now that we have a rough picture of what our persistence logic might look like, it's natural to ask how we should test our code.

0 commit comments

Comments
 (0)