HHH-16666 document fetch profiles now they are nicer to use

This commit is contained in:
Gavin 2023-05-22 17:10:21 +02:00 committed by Gavin King
parent 36a77785e8
commit e12b82033e
2 changed files with 94 additions and 2 deletions

View File

@ -688,3 +688,95 @@ byte[] image;
Interception is able to detect writes to the `image` field, that is, replacement of the whole array.
It's not able to detect modifications made directly to the _elements_ of the array, and so such modifications may be lost.
====
[[fetch-profiles]]
=== Named fetch profiles
We've already seen two different ways to override the default <<association-fetching,fetching strategy>> for an association:
- <<entity-graph,JPA entity graphs>>, and
- the `join fetch` clause in <<hql-queries,HQL>>, or, equivalently, the method `From.fetch()` in the criteria query API.
A third way is to define a named fetch profile.
First, we must declare the profile, by annotating a class or package:
[source,java]
----
@FetchProfile(name = "EagerBook")
@Entity
class Book { ... }
----
Note that even though we've placed this annotation on the `Book` entity, a fetch profile—unlike an entity graph—isn't "rooted" at any particular entity.
We may specify association fetching strategies using the `fetchOverrides` member of the `@FetchProfile` annotation, but frankly it looks so messy that we're embarrassed to show it to you here.
A better way is to annotate an association with the fetch profiles it should be fetched in:
[source,java]
----
@FetchProfile(name = "EagerBook")
@Entity
class Book {
...
@ManyToOne(fetch = LAZY)
@Fetch(profile = "EagerBook", value = JOIN)
Publisher publisher;
@ManyToMany
@Fetch(profile = "EagerBook", value = JOIN)
Set<Author> authors;
...
}
----
[source,java]
----
@Entity
class Author {
...
@OneToOne
@Fetch(profile = "EagerBook", value = JOIN)
Person person;
...
}
----
We may define as many different fetch profiles as we like.
[NOTE]
====
JPA entity graphs may also be defined in annotations, using `@NamedEntityGraph`.
But the format of this annotation is _even worse_ than the format of the `@FetchProfile` annotation, so we can't recommend it. 💀
====
.Annotations for defining fetch profiles
[%autowidth.stretch]
|===
| Annotation | Purpose
| `@FetchProfile` | Declares a named fetch profile, optionally including a list of ``@FetchOverride``s
| `@FetchProfile.FetchOverride` | Declares a fetch strategy override as part of the `@FetchProfile` declaration
| `@Fetch` | Specifies the fetch strategy for the annotated association, in a given fetch profile
|===
A fetch profile must be explicitly enabled for a given session:
[source,java]
----
session.enableFetchProfile("EagerBook");
Book eagerBook = session.find(Book.class, bookId);
----
[TIP]
====
To make this a bit typesafe, it's a really good idea to put the name of the fetch profile in a `static final` constant.
====
So why might we prefer named fetch profiles to entity graphs?
Well, that's really hard to say.
It's nice that this feature _exists_, and if you love it, that's great.
But Hibernate offers alternatives that we think are more compelling most of the time.

View File

@ -161,9 +161,9 @@ It's saying that you must explicitly specify eager fetching for associations pre
If you need eager fetching in some particular transaction, use:
- `left join fetch` in HQL,
- `fetch()` in a criteria query,
- `From.fetch()` in a criteria query,
- a JPA `EntityGraph`, or
- a fetch profile.
- a <<fetch-profiles,fetch profile>>.
You can find much more information about association fetching in the {association-fetching}[User Guide].