update the docs with new @FetchProfileOverride

and the "default" profile
This commit is contained in:
Gavin 2023-05-23 14:27:45 +02:00 committed by Gavin King
parent 66d67795a3
commit 2e502215d5
2 changed files with 39 additions and 16 deletions

View File

@ -721,11 +721,11 @@ class Book {
...
@ManyToOne(fetch = LAZY)
@Fetch(profile = "EagerBook", value = JOIN)
@FetchProfileOverride(profile = "EagerBook", mode = JOIN)
Publisher publisher;
@ManyToMany
@Fetch(profile = "EagerBook", value = JOIN)
@FetchProfileOverride(profile = "EagerBook", mode = JOIN)
Set<Author> authors;
...
@ -738,7 +738,7 @@ class Author {
...
@OneToOne
@Fetch(profile = "EagerBook", value = JOIN)
@FetchProfileOverride(profile = "EagerBook", mode = JOIN)
Person person;
...
@ -756,12 +756,12 @@ class Book {
...
@OneToOne
@Fetch(profile = "EagerBook", value = JOIN)
@FetchProfileOverride(profile = "EagerBook", mode = JOIN)
Person person;
@ManyToMany
@Fetch(profile = "EagerBook", value = JOIN)
@Fetch(profile = "BookWithAuthorsBySubselect", value = SUBSELECT)
@FetchProfileOverride(profile = "EagerBook", mode = JOIN)
@FetchProfileOverride(profile = "BookWithAuthorsBySubselect", mode = SUBSELECT)
Set<Author> authors;
...
@ -783,7 +783,7 @@ But the format of this annotation is _even worse_ than the format of the `@Fetch
| `@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
| `@FetchProfileOverride` | Specifies the fetch strategy for the annotated association, in a given fetch profile
|===
A fetch profile must be explicitly enabled for a given session:
@ -806,3 +806,18 @@ But Hibernate offers alternatives that we think are more compelling most of the
The one and only advantage unique to fetch profiles is that they let us very selectively request subselect fetching.
We can't do that with entity graphs, and we can't do it with HQL.
[TIP]
====
There's a special built-in fetch profile named `org.hibernate.defaultProfile` which is defined as the profile with `@FetchProfileOverride(mode=JOIN)` applied to every eager `@ManyToOne` or `@OneToOne` association.
If you enable this profile:
[source,java]
----
session.enableFetchProfile("org.hibernate.defaultProfile");
----
Then ``outer join``s for such associations will _automatically_ be added to every HQL or criteria query.
This is nice if you can't be bothered typing out those ``join fetch``es explicitly.
And in principle it even helps partially mitigate the <<many-to-one,problem>> of JPA having specified the wrong default for the `fetch` member of `@ManyToOne`.
====

View File

@ -130,7 +130,6 @@ Of these, you should almost always use outer join fetching.
=== Batch fetching and subselect fetching
Both batch fetching and subselect fetching are disabled by default, but we may enable one or the other globally using properties.
Later, we'll see how we can use <<fetch-profiles,fetch profiles>> to do this more selectively.
.Configuration settings to enable batch and subselect fetching
[cols="35,~"]
@ -141,13 +140,13 @@ Later, we'll see how we can use <<fetch-profiles,fetch profiles>> to do this mor
| `hibernate.use_subselect_fetch` | `true` to enable subselect fetching
|===
That's all there is to it.
Too easy, right?
Alternatively, we can enable one or the other in a given session:
Sadly, that's not the end of the story.
While batch fetching might _mitigate_ problems involving N+1 selects, it won't solve them.
The truly correct solution is to fetch associations using joins.
Batch fetching (or subselect fetching) can only be the _best_ solution in rare cases where outer join fetching would result in a cartesian product and a huge result set.
[source,java]
----
session.setFetchBatchSize(5);
session.setSubselectFetchingEnabled(true);
----
[TIP]
====
@ -160,15 +159,24 @@ Set<Author> authors;
Note that `@Fetch(SUBSELECT)` is equivalent to `@Fetch(SELECT)`, except after execution of a
HQL or criteria query.
We'll see more of `@Fetch` when we discuss <<fetch-profiles,fetch profiles>>.
Later, we'll see how we can use <<fetch-profiles,fetch profiles>> to do this even more selectively.
====
That's all there is to it.
Too easy, right?
Sadly, that's not the end of the story.
While batch fetching might _mitigate_ problems involving N+1 selects, it won't solve them.
The truly correct solution is to fetch associations using joins.
Batch fetching (or subselect fetching) can only be the _best_ solution in rare cases where outer join fetching would result in a cartesian product and a huge result set.
Batch fetching and subselect fetching have one important characteristic in common: they can be performed _lazily_.
[[join-fetch]]
==== Join fetching
=== Join fetching
Unfortunately, outer join fetching, by nature, simply can't be lazy.
So:
TIP: Avoid the use of lazy fetching, which is often the source of N+1 selects.