document EntityGraphs

This commit is contained in:
Gavin 2023-05-19 15:48:53 +02:00
parent 56ffbc104c
commit 8ddbb033cd
2 changed files with 67 additions and 1 deletions

View File

@ -337,6 +337,72 @@ We're getting a bit ahead of ourselves here, but let's quickly mention the gener
Instead, fetch all the data you'll need upfront at the beginning of a unit of work, using one of the techniques described in <<association-fetching>>, usually, using _join fetch_ in HQL. Instead, fetch all the data you'll need upfront at the beginning of a unit of work, using one of the techniques described in <<association-fetching>>, usually, using _join fetch_ in HQL.
==== ====
It's clear we need a way to request that an association be _eagerly_ fetched using a database `join`.
One way to do that is by passing an `EntityGraph` to `find()`.
[[entity-graph]]
=== Entity graphs and eager fetching
When an association is mapped `fetch=LAZY`, it won't, by default, be fetched when we call the `find()` method.
We may request that an association be fetched eagerly (immediately) by passing an `EntityGraph` to `find()`.
The JPA-standard API for this is a bit unwieldy:
[source,java]
----
var graph = entityManager.createEntityGraph(Book.class);
graph.addSubgraph(Book_.publisher);
entityManager.find(Book.class, bookId, Map.of(SpecHints.HINT_SPEC_FETCH_GRAPH, graph));
----
This is untypesafe and a bit verbose.
Hibernate has a better way:
[source,java]
----
var graph = session.createEntityGraph(Book.class);
graph.addSubgraph(Book_.publisher);
session.byId(Book.class).fetching(graph).load(bookId);
----
This code adds a `left outer join` to our SQL query, fetching the associated `Publisher` along with the `Book`.
We may even attach additional nodes to our `EntityGraph`:
[source,java]
----
var graph = session.createEntityGraph(Book.class);
graph.addSubgraph(Book_.publisher);
graph.addPluralSubgraph(Book_.authors).addSubgraph(Author_.person);
session.byId(Book.class).fetching(graph).load(bookId);
----
This results in a SQL query with _four_ ``left outer join``s.
[NOTE]
====
In the code examples above, we're making use of the JPA static metamodel.
The classes `Book_` and `Author_` are generated by the annotation processor we have in our <<hello-hibernate,gradle build>>, one of the <<optional-dependencies,optional dependencies>> of Hibernate.
They let us refer to attributes of our model in a completely type-safe way.
We'll use them again, below, when we talk about <<criteria-queries>>.
====
JPA specifies that any given `EntityGraph` may be interpreted in two different ways.
- A _fetch graph_ specifies exactly the associations that should be eagerly loaded.
Any association not belonging to the entity graph is proxied and loaded lazily only if required.
- A _load graph_ specifies that the associations in the entity graph are to be fetched in addition to the associations mapped `fetch=EAGER`.
You're right, the names make no sense.
But don't worry, if you take our advice, and map your associations `fetch=LAZY`, there's no difference between a "fetch" graph and a "load" graph, so the names don't matter.
[NOTE]
====
JPA even specifies a way to define named entity graphs using annotations.
But the annotation-based API is so verbose that it's just not worth using.
====
[[flush]] [[flush]]
=== Flushing the session === Flushing the session

View File

@ -559,7 +559,7 @@ So we don't usually need to explicitly specify that a column should be of type `
The constant values defined in the class `org.hibernate.Length` are very helpful here: The constant values defined in the class `org.hibernate.Length` are very helpful here:
.Predefined column lengths .Predefined column lengths
[%autowidth.stretch] [cols="10,12,~"]
|=== |===
| Constant | Value | Description | Constant | Value | Description