Skip to content

Commit 3a2d4bc

Browse files
committed
Merge branch 'o-main' into main-perf
2 parents 22575ae + 43954c4 commit 3a2d4bc

File tree

486 files changed

+18862
-5377
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

486 files changed

+18862
-5377
lines changed

.github/hibernate-github-bot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
---
22
jira:
33
projectKey: "HHH"
4+
insertLinksInPullRequests: true

docker_db.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ mssql_2022() {
320320
sybase() {
321321
$CONTAINER_CLI rm -f sybase || true
322322
# Yup, that sucks, but on ubuntu we need to use -T11889 as per: https://github.com/DataGrip/docker-env/issues/12
323-
$CONTAINER_CLI run -d -p 5000:5000 -p 5001:5001 --name sybase --entrypoint /bin/bash docker.io/nguoianphu/docker-sybase -c "source /opt/sybase/SYBASE.sh
323+
$CONTAINER_CLI run -d -p 9000:5000 -p 9001:5001 --name sybase --entrypoint /bin/bash docker.io/nguoianphu/docker-sybase -c "source /opt/sybase/SYBASE.sh
324324
/opt/sybase/ASE-16_0/bin/dataserver \
325325
-d/opt/sybase/data/master.dat \
326326
-e/opt/sybase/ASE-16_0/install/MYSYBASE.log \

documentation/src/main/asciidoc/introduction/Configuration.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ SessionFactory sessionFactory =
219219
.setProperty(AvailableSettings.JAKARTA_JDBC_PASSWORD, password)
220220
// Automatic schema export
221221
.setProperty(AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION,
222-
Action.CREATE.getExternalJpaName())
222+
Action.SPEC_ACTION_DROP_AND_CREATE)
223223
// SQL statement logging
224224
.setProperty(AvailableSettings.SHOW_SQL, TRUE.toString())
225225
.setProperty(AvailableSettings.FORMAT_SQL, TRUE.toString())

documentation/src/main/asciidoc/introduction/Generator.adoc

Lines changed: 670 additions & 0 deletions
Large diffs are not rendered by default.

documentation/src/main/asciidoc/introduction/Hibernate_Introduction.adoc

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,25 @@ Gavin King and the Hibernate team
1313
:toc:
1414
:toclevels: 3
1515

16-
<<<
17-
1816
include::Preface.adoc[]
1917

20-
<<<
21-
2218
:numbered:
2319

2420
include::Introduction.adoc[]
2521

26-
<<<
27-
2822
include::Configuration.adoc[]
2923

30-
<<<
31-
3224
include::Entities.adoc[]
3325

34-
<<<
35-
3626
include::Mapping.adoc[]
3727

38-
<<<
39-
4028
include::Interacting.adoc[]
4129

42-
// include::../userguide/chapters/query/hql/Hibernate_Query_Language.adoc[]
30+
include::Generator.adoc[]
4331

44-
<<<
32+
// include::../userguide/chapters/query/hql/Hibernate_Query_Language.adoc[]
4533

4634
include::Tuning.adoc[]
4735

48-
<<<
49-
5036
include::Advanced.adoc[]
5137

documentation/src/main/asciidoc/introduction/Interacting.adoc

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ A persistence context—that is, a `Session` or `EntityManager`—absolutely pos
6161
If you accidentally leak a session across threads, you will suffer.
6262
====
6363

64-
.Container-managed peristence contexts
64+
.Container-managed persistence contexts
6565
****
6666
In a container environment, the lifecycle of a persistence context scoped to the transaction will usually be managed for you.
6767
****
@@ -279,7 +279,7 @@ But there's a way to set things up so that an operation will propagate to associ
279279
[[cascade]]
280280
=== Cascading persistence operations
281281

282-
It's quite often the case that the lifecycle of a _child_ entity is completely dependent on the lifeycle of some _parent_.
282+
It's quite often the case that the lifecycle of a _child_ entity is completely dependent on the lifecycle of some _parent_.
283283
This is especially common for many-to-one and one-to-one associations, though it's very rare for many-to-many associations.
284284

285285
For example, it's quite common to make an `Order` and all its ``Item``s persistent in the same transaction, or to delete a `Project` and its ``Files``s at once.
@@ -652,14 +652,14 @@ Using the JPA-standard APIs, this would be a `CriteriaBuilder`, and we get it fr
652652

653653
[source,java]
654654
----
655-
CriteriaBuilder cb = entityManagerFactory.getCriteriaBuilder();
655+
CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();
656656
----
657657

658658
But if we have a `SessionFactory`, we get something much better, a `HibernateCriteriaBuilder`:
659659

660660
[source,java]
661661
----
662-
HibernateCriteriaBuilder cb = sessionFactory.getCriteriaBuilder();
662+
HibernateCriteriaBuilder builder = sessionFactory.getCriteriaBuilder();
663663
----
664664

665665
The `HibernateCriteriaBuilder` extends `CriteriaBuilder` and adds many operations that JPQL doesn't have.
@@ -672,15 +672,15 @@ Either:
672672
673673
[source,java]
674674
----
675-
HibernateCriteriaBuilder cb =
675+
HibernateCriteriaBuilder builder =
676676
entityManagerFactory.unwrap(SessionFactory.class).getCriteriaBuilder();
677677
----
678678
679679
Or simply:
680680
681681
[source,java]
682682
----
683-
HibernateCriteriaBuilder cb =
683+
HibernateCriteriaBuilder builder =
684684
(HibernateCriteriaBuilder) entityManagerFactory.getCriteriaBuilder();
685685
----
686686
====
@@ -689,18 +689,18 @@ We're ready to create a criteria query.
689689

690690
[source,java]
691691
----
692-
CriteriaQuery<Book> query = cb.createQuery(Book.class);
692+
CriteriaQuery<Book> query = builder.createQuery(Book.class);
693693
Root<Book> book = query.from(Book.class);
694-
Predicate where = cb.conjunction();
694+
Predicate where = builder.conjunction();
695695
if (titlePattern != null) {
696-
where = cb.and(where, cb.like(book.get(Book_.title), titlePattern));
696+
where = builder.and(where, builder.like(book.get(Book_.title), titlePattern));
697697
}
698698
if (namePattern != null) {
699699
Join<Book,Author> author = book.join(Book_.author);
700-
where = cb.and(where, cb.like(author.get(Author_.name), namePattern));
700+
where = builder.and(where, builder.like(author.get(Author_.name), namePattern));
701701
}
702702
query.select(book).where(where)
703-
.orderBy(cb.asc(book.get(Book_.title)));
703+
.orderBy(builder.asc(book.get(Book_.title)));
704704
----
705705

706706
Here, as before, the classes `Book_` and `Author_` are generated by Hibernate's <<metamodel-generator,JPA Metamodel Generator>>.
@@ -739,9 +739,9 @@ Update, insert, and delete queries work similarly:
739739

740740
[source,java]
741741
----
742-
CriteriaDelete<Book> delete = cb.createCriteriaDelete(Book.class);
742+
CriteriaDelete<Book> delete = builder.createCriteriaDelete(Book.class);
743743
Root<Book> book = delete.from(Book.class);
744-
delete.where(cb.lt(cb.year(book.get(Book_.publicationDate)), 2000));
744+
delete.where(builder.lt(builder.year(book.get(Book_.publicationDate)), 2000));
745745
session.createMutationQuery(delete).executeUpdate();
746746
----
747747

@@ -750,15 +750,47 @@ session.createMutationQuery(delete).executeUpdate();
750750
It's even possible to transform a HQL query string to a criteria query, and modify the query programmatically before execution:
751751
[source,java]
752752
----
753-
HibernateCriteriaBuilder cb = sessionFactory.getCriteriaBuilder();
754-
var query = cb.createQuery("from Book where year(publicationDate) > 2000", Book.class);
753+
HibernateCriteriaBuilder builder = sessionFactory.getCriteriaBuilder();
754+
var query = builder.createQuery("from Book where year(publicationDate) > 2000", Book.class);
755755
var root = (Root<Book>) query.getRootList().get(0);
756-
query.where(cb.like(root.get(Book_.title), cb.literal("Hibernate%")));
757-
query.orderBy(cb.asc(root.get(Book_.title)), cb.desc(root.get(Book_.isbn)));
756+
query.where(builder.like(root.get(Book_.title), builder.literal("Hibernate%")));
757+
query.orderBy(builder.asc(root.get(Book_.title)), builder.desc(root.get(Book_.isbn)));
758758
List<Book> matchingBooks = session.createSelectionQuery(query).getResultList();
759759
----
760760
====
761761

762+
Do you find some of the code above a bit too verbose?
763+
We do.
764+
765+
[[criteria-definition]]
766+
=== A more comfortable way to write criteria queries
767+
768+
Actually, what makes the JPA criteria API less ergonomic that it should be is the need to call all operations of the `CriteriaBuilder` as instance methods, instead of having them as `static` functions.
769+
The reason it works this way is that each JPA providor has its own implementation of `CriteriaBuilder`.
770+
771+
// [%unbreakable]
772+
// [TIP]
773+
// ====
774+
Hibernate 6.3 introduces the helper class `CriteriaDefinition` to reduce the verbosity of criteria queries.
775+
Our example looks like this:
776+
777+
[source,java]
778+
----
779+
CriteriaQuery<Book> query =
780+
new CriteriaDefinition(entityManagerFactory, Book.class) {{
781+
select(book);
782+
if (titlePattern != null) {
783+
restrict(like(book.get(Book_.title), titlePattern));
784+
}
785+
if (namePattern != null) {
786+
var author = book.join(Book_.author);
787+
restrict(like(author.get(Author_.name), namePattern));
788+
}
789+
orderBy(asc(book.get(Book_.title)));
790+
}};
791+
----
792+
// ====
793+
762794
When all else fails, and sometimes even before that, we're left with the option of writing a query in SQL.
763795

764796
[[native-queries]]
@@ -859,7 +891,7 @@ For example, this:
859891
List<Book> books =
860892
session.createSelectionQuery("from Book where title like ?1 order by title")
861893
.setParameter(1, titlePattern)
862-
.setMaxResults(10)
894+
.setMaxResults(MAX_RESULTS)
863895
.getResultList();
864896
----
865897

@@ -870,22 +902,32 @@ is simpler than:
870902
List<Book> books =
871903
session.createSelectionQuery("from Book where title like ?1 order by title fetch first ?2 rows only")
872904
.setParameter(1, titlePattern)
873-
.setParameter(2, 10)
905+
.setParameter(2, MAX_RESULTS)
906+
.getResultList();
907+
----
908+
909+
Hibernate's `SelectionQuery` has a slightly different way to paginate the query results:
910+
911+
[source,java]
912+
----
913+
List<Book> books =
914+
session.createSelectionQuery("from Book where title like ?1 order by title")
915+
.setParameter(1, titlePattern)
916+
.setPage(Page.first(MAX_RESULTS))
874917
.getResultList();
875918
----
876919

877920
A closely-related issue is ordering.
878921
It's quite common for pagination to be combined with the need to order query results by a field that's determined at runtime.
879-
So, as an alternative to the HQL `order by` clause, Hibernate's `SelectionQuery` interface 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:
922+
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:
880923

881924
[source,java]
882925
----
883926
List<Book> books =
884927
session.createSelectionQuery("from Book where title like ?1")
885928
.setParameter(1, titlePattern)
886-
.ascending(Book._title)
887-
.ascending(Book._isbn)
888-
.setMaxResults(10)
929+
.setOrder(List.of(Order.asc(Book._title), Order.asc(Book._isbn)))
930+
.setMaxResults(MAX_RESULTS)
889931
.getResultList();
890932
----
891933

@@ -898,9 +940,8 @@ Unfortunately, there's no way to do this using JPA's `TypedQuery` interface.
898940

899941
| `setMaxResults()` | Set a limit on the number of results returned by a query | &#10004;
900942
| `setFirstResult()` | Set an offset on the results returned by a query | &#10004;
901-
| `ascending()` | Add a field to use to order the results | &#10006;
902-
| `descending()` | Add a field to use to order the results | &#10006;
903-
| `unordered()` | Clear any current ordering | &#10006;
943+
| `setPage()` | Set the limit and offset by specifying a `Page` object | &#10006;
944+
| `setOrder()` | Specify how the query results should be ordered | &#10006;
904945
|===
905946

906947
[[projection-lists]]
@@ -951,13 +992,13 @@ Consider the following code:
951992

952993
[source,java]
953994
----
954-
var cb = sessionFactory.getCriteriaBuilder();
955-
var query = cb.createTupleQuery();
995+
var builder = sessionFactory.getCriteriaBuilder();
996+
var query = builder.createTupleQuery();
956997
var book = query.from(Book.class);
957998
var bookTitle = book.get(Book_.title);
958999
var bookIsbn = book.get(Book_.isbn);
9591000
var bookPrice = book.get(Book_.price);
960-
query.select(cb.tuple(bookTitle, bookIsbn, bookPrice));
1001+
query.select(builder.tuple(bookTitle, bookIsbn, bookPrice));
9611002
var resultList = session.createSelectionQuery(query).getResultList();
9621003
for (var result: resultList) {
9631004
String title = result.get(bookTitle);
@@ -1032,9 +1073,10 @@ Note that the code which executes the named query is not aware of whether the qu
10321073
10331074
It's nice to have our queries checked at startup time.
10341075
It's even better to have them checked at compile time.
1035-
Back in <<generated-query-methods>>, we mentioned that the {query-validator}[Query Validator] can do that for us.
1036-
In fact, the Query Validator will even check HQL query strings that occur as arguments to `createQuery()` and friends.
1037-
So if we use the Query Validator, there's not much advantage to the use of named queries.
1076+
Back in <<generated-query-methods>>, we mentioned that the Metamodel Generator can do that for us, and we presented that as a reason to use `@NamedQuery`.
1077+
1078+
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.
1079+
If we use the Query Validator, there's not much advantage to the use of named queries.
10381080
====
10391081

10401082
[[load-access]]

0 commit comments

Comments
 (0)