Remove some 6.3 references from documentation
This commit is contained in:
parent
0d8541a272
commit
4158c7a0eb
|
@ -64,15 +64,13 @@ class User {
|
|||
}
|
||||
----
|
||||
|
||||
Here, as usual, `example_.BY_REGION` is generated by the Metamodel Generator, and is just a constant with the value `"ByRegion"`.
|
||||
|
||||
If the `@Filter` annotation does not explicitly specify a restriction, the default restriction given by the `@FilterDef` will be applied to the entity.
|
||||
But an entity is free to override the default condition.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Entity
|
||||
@Filter(name = example_.FILTER_BY_REGION, condition = "name = :region")
|
||||
@Filter(name = "ByRegion", condition = "name = :region")
|
||||
class Region {
|
||||
|
||||
@Id String name;
|
||||
|
@ -99,7 +97,7 @@ You should do this right at the _start_ of the session.
|
|||
[source,java]
|
||||
----
|
||||
sessionFactory.inTransaction(session -> {
|
||||
session.enableFilter(example_.FILTER_BY_REGION)
|
||||
session.enableFilter("ByRegion")
|
||||
.setParameter("region", "es")
|
||||
.validate();
|
||||
|
||||
|
@ -257,7 +255,7 @@ Native SQL queries are _not_ automatically filtered by tenant id; you'll have to
|
|||
|
||||
[TIP]
|
||||
====
|
||||
If you only need to filter rows by a static condition with no parameters, `@SQLRestriction` is a much simpler way to do that.
|
||||
If you only need to filter rows by a static condition with no parameters, `@Where` is a much simpler way to do that.
|
||||
====
|
||||
|
||||
[[custom-sql]]
|
||||
|
@ -648,7 +646,6 @@ These annotations allow us to specify how the elements of a collection should be
|
|||
| Annotation | Purpose | JPA-standard
|
||||
|
||||
| `@OrderBy` | Specifies a fragment of JPQL used to order the collection | ✔
|
||||
| `@SQLOrder` | Specifies a fragment of SQL used to order the collection | ✖
|
||||
|===
|
||||
|
||||
On the other hand, the following annotation specify how a collection should be sorted in memory, and are used for collections of type `SortedSet` or `SortedMap`:
|
||||
|
@ -902,7 +899,7 @@ 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.
|
||||
We may specify association fetching strategies using the `fetchOverrides` member of the `@FetchProfile` annotation.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
|
@ -914,17 +911,19 @@ A better way is to annotate an association with the fetch profiles it should be
|
|||
|
||||
[source,java]
|
||||
----
|
||||
@FetchProfile(name = "EagerBook")
|
||||
@FetchProfile(name = "EagerBook", fetchOverrides = {
|
||||
@FetchProfile.FetchOverride(entity = Book.class, association = "publisher", mode = JOIN),
|
||||
@FetchProfile.FetchOverride(entity = Book.class, association = "authors", mode = JOIN),
|
||||
@FetchProfile.FetchOverride(entity = Author.class, association = "person", mode = JOIN)
|
||||
})
|
||||
@Entity
|
||||
class Book {
|
||||
...
|
||||
|
||||
@ManyToOne(fetch = LAZY)
|
||||
@FetchProfileOverride(profile = Book_.PROFILE_EAGER_BOOK, mode = JOIN)
|
||||
Publisher publisher;
|
||||
|
||||
@ManyToMany
|
||||
@FetchProfileOverride(profile = Book_.PROFILE_EAGER_BOOK, mode = JOIN)
|
||||
Set<Author> authors;
|
||||
|
||||
...
|
||||
|
@ -937,33 +936,31 @@ class Author {
|
|||
...
|
||||
|
||||
@OneToOne
|
||||
@FetchProfileOverride(profile = Book_.PROFILE_EAGER_BOOK, mode = JOIN)
|
||||
Person person;
|
||||
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
Here, once again, `Book_.PROFILE_EAGER_BOOK` is generated by the Metamodel Generator, and is just a constant with the value `"EagerBook"`.
|
||||
|
||||
For collections, we may even request subselect fetching:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@FetchProfile(name = "EagerBook")
|
||||
@FetchProfile(name = "BookWithAuthorsBySubselect")
|
||||
@FetchProfile(name = "EagerBook", fetchOverrides = {
|
||||
@FetchProfile.FetchOverride(entity = Book.class, association = "person", mode = JOIN),
|
||||
@FetchProfile.FetchOverride(entity = Book.class, association = "authors", mode = JOIN)
|
||||
})
|
||||
@FetchProfile(name = "BookWithAuthorsBySubselect", fetchOverrides = {
|
||||
@FetchProfile.FetchOverride(entity = Book.class, association = "authors", mode = SUBSELECT)
|
||||
})
|
||||
@Entity
|
||||
class Book {
|
||||
...
|
||||
|
||||
@OneToOne
|
||||
@FetchProfileOverride(profile = Book_.PROFILE_EAGER_BOOK, mode = JOIN)
|
||||
Person person;
|
||||
|
||||
@ManyToMany
|
||||
@FetchProfileOverride(profile = Book_.PROFILE_EAGER_BOOK, mode = JOIN)
|
||||
@FetchProfileOverride(profile = Book_.BOOK_WITH_AUTHORS_BY_SUBSELECT,
|
||||
mode = SUBSELECT)
|
||||
Set<Author> authors;
|
||||
|
||||
...
|
||||
|
@ -979,14 +976,13 @@ We may define as many different fetch profiles as we like.
|
|||
|
||||
| `@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
|
||||
| `@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:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
session.enableFetchProfile(Book_.PROFILE_EAGER_BOOK);
|
||||
session.enableFetchProfile("EagerBook");
|
||||
Book eagerBook = session.find(Book.class, bookId);
|
||||
----
|
||||
|
||||
|
@ -997,18 +993,3 @@ 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 <<lazy-problem,problem>> of JPA having specified the wrong default for the `fetch` member of `@ManyToOne`.
|
||||
====
|
||||
|
|
|
@ -742,20 +742,6 @@ delete.where(builder.lt(builder.year(book.get(Book_.publicationDate)), 2000));
|
|||
session.createMutationQuery(delete).executeUpdate();
|
||||
----
|
||||
|
||||
[TIP]
|
||||
====
|
||||
It's even possible to transform a HQL query string to a criteria query, and modify the query programmatically before execution:
|
||||
[source,java]
|
||||
----
|
||||
HibernateCriteriaBuilder builder = sessionFactory.getCriteriaBuilder();
|
||||
var query = builder.createQuery("from Book where year(publicationDate) > 2000", Book.class);
|
||||
var root = (Root<Book>) query.getRootList().get(0);
|
||||
query.where(builder.like(root.get(Book_.title), builder.literal("Hibernate%")));
|
||||
query.orderBy(builder.asc(root.get(Book_.title)), builder.desc(root.get(Book_.isbn)));
|
||||
List<Book> matchingBooks = session.createSelectionQuery(query).getResultList();
|
||||
----
|
||||
====
|
||||
|
||||
When all else fails, and sometimes even before that, we're left with the option of writing a query in SQL.
|
||||
|
||||
[[native-queries]]
|
||||
|
@ -878,24 +864,12 @@ Hibernate's `SelectionQuery` has a slightly different way to paginate the query
|
|||
List<Book> books =
|
||||
session.createSelectionQuery("from Book where title like ?1 order by title")
|
||||
.setParameter(1, titlePattern)
|
||||
.setPage(Page.first(MAX_RESULTS))
|
||||
.getResultList();
|
||||
----
|
||||
|
||||
A closely-related issue is ordering.
|
||||
It's quite common for pagination to be combined with the need to order query results by a field that's determined at runtime.
|
||||
So, as an alternative to the HQL `order by` clause, `SelectionQuery` offers the ability to specify that the query results should be ordered by one or more fields of the entity type returned by the query:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
List<Book> books =
|
||||
session.createSelectionQuery("from Book where title like ?1")
|
||||
.setParameter(1, titlePattern)
|
||||
.setOrder(List.of(Order.asc(Book._title), Order.asc(Book._isbn)))
|
||||
.setMaxResults(MAX_RESULTS)
|
||||
.getResultList();
|
||||
----
|
||||
|
||||
A closely-related issue is ordering, for which Hibernate ORM 6.3 offers an incubating API.
|
||||
|
||||
Unfortunately, there's no way to do this using JPA's `TypedQuery` interface.
|
||||
|
||||
.Methods for query limits, pagination, and ordering
|
||||
|
@ -1021,13 +995,11 @@ We execute our named query like this:
|
|||
[source,java]
|
||||
----
|
||||
List<Book> books =
|
||||
entityManager.createNamedQuery(BookQueries_.QUERY_10_BOOKS_BY_TITLE)
|
||||
entityManager.createNamedQuery("10BooksByTitle")
|
||||
.setParameter("titlePattern", titlePattern)
|
||||
.getResultList()
|
||||
----
|
||||
|
||||
Here, `BookQueries_.QUERY_10_BOOKS_BY_TITLE` is a constant with value `"10BooksByTitle"`, generated by the Metamodel Generator.
|
||||
|
||||
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.
|
||||
|
||||
[TIP]
|
||||
|
|
|
@ -500,13 +500,11 @@ This is an example of a _query method_, a function which accepts arguments to th
|
|||
And that's all it does; it doesn't orchestrate additional program logic, and it doesn't perform transaction or session management.
|
||||
|
||||
It's even better to specify the query string using the `@NamedQuery` annotation, so that Hibernate can validate the query it at startup time, that is, when the `SessionFactory` is created, instead of when the query is first executed.
|
||||
Indeed, since we included the <<metamodel-generator,Metamodel Generator>> in our <<build-gradle,Gradle build>>, the query can even be validated at _compile time_.
|
||||
|
||||
We need a place to put the annotation, so lets move our query method to a new class:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@CheckHQL // validate named queries at compile time
|
||||
@NamedQuery(name="findBooksByTitle",
|
||||
query="from Book where title like :title order by title")
|
||||
class Queries {
|
||||
|
|
|
@ -225,7 +225,6 @@ Both batch fetching and subselect fetching are disabled by default, but we may e
|
|||
| Configuration property name | Property value | Alternatives
|
||||
|
||||
| `hibernate.default_batch_fetch_size` | A sensible batch size `>1` to enable batch fetching | `@BatchSize()`, `setFetchBatchSize()`
|
||||
| `hibernate.use_subselect_fetch` | `true` to enable subselect fetching | `@Fetch(SUBSELECT)`, `setSubselectFetchingEnabled()`
|
||||
|===
|
||||
|
||||
Alternatively, we can enable one or the other in a given session:
|
||||
|
@ -233,7 +232,6 @@ Alternatively, we can enable one or the other in a given session:
|
|||
[source,java]
|
||||
----
|
||||
session.setFetchBatchSize(5);
|
||||
session.setSubselectFetchingEnabled(true);
|
||||
----
|
||||
|
||||
[%unbreakable]
|
||||
|
|
Loading…
Reference in New Issue