You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation/src/main/asciidoc/introduction/Advanced.adoc
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -66,7 +66,7 @@ class User {
66
66
}
67
67
----
68
68
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"`.
70
70
71
71
If the `@Filter` annotation does not explicitly specify a restriction, the default restriction given by the `@FilterDef` will be applied to the entity.
72
72
But an entity is free to override the default condition.
@@ -1081,7 +1081,7 @@ class Author {
1081
1081
}
1082
1082
----
1083
1083
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"`.
1085
1085
1086
1086
For collections, we may even request subselect fetching:
Copy file name to clipboardExpand all lines: documentation/src/main/asciidoc/introduction/Generator.adoc
+40-30Lines changed: 40 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,19 +1,19 @@
1
1
[[generator]]
2
2
== Compile-time tooling
3
3
4
-
The Metamodel Generator is a standard part of JPA.
4
+
The _static metamodel generator_ is a standard part of JPA.
5
5
// 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`.
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 typesafe way to refer to their attributes in Java code.
17
17
In particular, it lets us specify <<entity-graph,entity graphs>> and <<criteria-queries,criteria queries>> in a completely type-safe way.
18
18
19
19
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
25
25
For years, Gavin counted this as one of his more embarrassing missteps.
26
26
27
27
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.
29
29
JPA's `CriteriaBuilder` and `EntityGraph` APIs are still not quite perfect, but the imperfections aren't related to static type safety or annotation processing.
30
30
The static metamodel itself is undeniably useful and elegant.
31
31
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.
34
35
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.
36
37
****
37
38
38
39
[TIP]
39
40
====
40
41
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.
42
43
====
43
44
44
45
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:
100
101
1. a `String`-valued constant like `TITLE` , and
101
102
2. a typesafe reference like `title` to a metamodel object of type `Attribute`.
102
103
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
-
106
104
[TIP]
107
105
====
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`.
109
107
110
108
[source,java]
111
109
----
@@ -118,16 +116,21 @@ This is very useful for writing generic code in frameworks or libraries.
118
116
For example, you could use it to create your own criteria query API.
119
117
====
120
118
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.
123
121
124
-
[CAUTION]
122
+
[NOTE]
125
123
====
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].
129
129
====
130
130
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
+
131
134
We're going to meet three different kinds of generated method:
132
135
133
136
- 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:
141
144
142
145
To whet our appetites, let's see how this works for a `@NamedQuery`.
143
146
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
+
144
154
[[generated-named-queries]]
145
-
=== Named queries and the Metamodel Generator
155
+
=== Named queries and Hibernate Processor
146
156
147
157
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 `#`.
148
158
@@ -157,7 +167,7 @@ Let's just stick it on the `Book` class:
157
167
public class Book { ... }
158
168
----
159
169
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_`.
161
171
162
172
[source,java]
163
173
.Generated Code
@@ -187,7 +197,7 @@ Now, this is quite nice, but it's a bit inflexible in various ways, and so this
187
197
=== Generated query methods
188
198
189
199
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.
191
201
192
202
The solution is to write down the signature of the query method _explicitly_, as an abstract method in Java.
193
203
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_ {
228
238
229
239
----
230
240
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.
232
242
233
243
If we want to explicitly specify the name and type of this parameter, we may declare it explicitly:
234
244
@@ -240,28 +250,28 @@ interface Queries {
240
250
}
241
251
----
242
252
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:
244
254
245
255
- `Session`,
246
256
- `StatelessSession`, or
247
257
- `Mutiny.Session` from Hibernate Reactive.
248
258
249
259
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:
251
261
252
262
- for a named parameter `:alice`, there must be a method parameter named `alice` with exactly the same type, or
253
263
- for an ordinal parameter `?2`, the second method parameter must have exactly the same type.
254
264
255
265
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.
257
267
258
268
[NOTE]
259
269
====
260
270
The `@CheckHQL` annotation which instructs Hibernate to validate named queries is _not_ necessary for query methods annotated `@HQL`.
261
271
====
262
272
263
273
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.
265
275
266
276
We imagine you're wondering whether a `static` method is really the right thing to use here.
267
277
@@ -290,7 +300,7 @@ interface Queries {
290
300
291
301
Here we've used `EntityManager` as the session type, but other types are allowed, as we saw above.
292
302
293
-
Now the Metamodel Generator does something a bit different:
303
+
Now Hibernate Processor does something a bit different:
294
304
295
305
[source,java]
296
306
.Generated Code
@@ -750,5 +760,5 @@ The Query Validator works in `javac`, Gradle, Maven, and the Eclipse Java Compil
750
760
751
761
[CAUTION]
752
762
====
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.
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>>.
863
863
864
864
[NOTE]
865
865
// .Injection attacks and criteria queries
@@ -1270,7 +1270,7 @@ List<Book> books =
1270
1270
.getResultList()
1271
1271
----
1272
1272
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.
1274
1274
1275
1275
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.
1276
1276
@@ -1280,7 +1280,7 @@ Note that the code which executes the named query is not aware of whether the qu
1280
1280
1281
1281
It's nice to have our queries checked at startup time.
1282
1282
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`.
1284
1284
1285
1285
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.
1286
1286
If we use the Query Validator, there's not much advantage to the use of named queries.
@@ -1352,7 +1352,7 @@ Book book =
1352
1352
.load();
1353
1353
----
1354
1354
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>>.
Copy file name to clipboardExpand all lines: documentation/src/main/asciidoc/introduction/Introduction.adoc
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -430,6 +430,7 @@ If you're new to Hibernate, frameworks which wrap JPA are quite likely to make y
430
430
We prefer a _bottom-up_ approach to organizing our code.
431
431
We like to start thinking about methods and functions, not about architectural layers and container-managed objects.
432
432
433
+
.Rethinking the persistence layer
433
434
****
434
435
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.
435
436
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
638
639
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.
639
640
You probably already have it available in your program.
640
641
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].
642
643
====
643
644
644
645
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