Skip to content

Commit

Permalink
HHH-18588 fix minor defects in Hibernate Introduction doc
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan.xu committed Sep 11, 2024
1 parent 2ada4ac commit c4a60fb
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 38 deletions.
2 changes: 1 addition & 1 deletion documentation/src/main/asciidoc/introduction/Advanced.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ public static class Person { ... }
| link:{doc-javadoc-url}org/hibernate/annotations/SQLSelect.html[`@SQLSelect`] | Overrides a generated SQL `select` statement
| link:{doc-javadoc-url}org/hibernate/annotations/SQLInsert.html[`@SQLInsert`] | Overrides a generated SQL `insert` statement
| link:{doc-javadoc-url}org/hibernate/annotations/SQLUpdate.html[`@SQLUpdate`] | Overrides a generated SQL `update` statement
| link:{doc-javadoc-url}org/hibernate/annotations/SQDelete.html[`@SQDelete`] | Overrides a generated SQL `delete` statement a single rows
| link:{doc-javadoc-url}org/hibernate/annotations/SQDelete.html[`@SQDelete`] | Overrides a generated SQL `delete` statement for a single row
| link:{doc-javadoc-url}org/hibernate/annotations/SQDeleteAll.html[`@SQDeleteAll`] | Overrides a generated SQL `delete` statement for multiple rows
| link:{doc-javadoc-url}org/hibernate/annotations/SQLRestriction.html[`@SQLRestriction`] | Adds a restriction to generated SQL
| link:{doc-javadoc-url}org/hibernate/annotations/SQLOrder.html[`@SQLOrder`] | Adds an ordering to generated SQL
Expand Down
14 changes: 7 additions & 7 deletions documentation/src/main/asciidoc/introduction/Configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
== Configuration and bootstrap

We would love to make this section short.
Unfortunately, there's several distinct ways to configure and bootstrap Hibernate, and we're going to have to describe at least two of them in detail.
Unfortunately, there are several distinct ways to configure and bootstrap Hibernate, and we're going to have to describe at least two of them in detail.

The four basic ways to obtain an instance of Hibernate are shown in the following table:

[%breakable,cols="50,50"]
[%breakable,cols="50,50",number=0]
|===

| Using the standard JPA-defined XML, and the operation `Persistence.createEntityManagerFactory()`
Expand Down Expand Up @@ -65,13 +65,13 @@ driver for your database.
| MySQL or TiDB | `com.mysql:mysql-connector-j:{version}`
| MariaDB | `org.mariadb.jdbc:mariadb-java-client:{version}`
| DB2 | `com.ibm.db2:jcc:{version}`
| SQL Server | `com.microsoft.sqlserver:mssql-jdbc:${version}`
| Oracle | `com.oracle.database.jdbc:ojdbc11:${version}`
| SQL Server | `com.microsoft.sqlserver:mssql-jdbc:{version}`
| Oracle | `com.oracle.database.jdbc:ojdbc11:{version}`
| H2 | `com.h2database:h2:{version}`
| HSQLDB | `org.hsqldb:hsqldb:{version}`
|===

Where `{version}` is the latest version of the JDBC driver for your databse.
Where `{version}` is the latest version of the JDBC driver for your database.

[[optional-dependencies]]
=== Optional dependencies
Expand Down Expand Up @@ -310,7 +310,7 @@ jakarta.persistence.database-major-version=15
jakarta.persistence.database-minor-version=7
----

The product name is the value returned by `java.sql.DatabaseMetaData.getDatabaseProductName()`, for example, `PostgreSQL`, `MySQL` `H2`, `Oracle`, `EnterpriseDB`, `MariaDB`, or `Microsoft SQL Server`.
The product name is the value returned by `java.sql.DatabaseMetaData.getDatabaseProductName()`, for example, `PostgreSQL`, `MySQL`, `H2`, `Oracle`, `EnterpriseDB`, `MariaDB`, or `Microsoft SQL Server`.

.Settings needed when database is inaccessible at startup
[%breakable,cols="50,~"]
Expand Down Expand Up @@ -424,7 +424,7 @@ Persistence.generateSchema("org.hibernate.example",

To see the generated SQL as it's sent to the database, you have two options.

One way is to set the property `hibernate.show_sql` to `true`, and Hibernate will log SQL direct to the console.
One way is to set the property `hibernate.show_sql` to `true`, and Hibernate will log SQL directly to the console.
You can make the output much more readable by enabling formatting or highlighting.
These settings really help when troubleshooting the generated SQL statements.

Expand Down
12 changes: 6 additions & 6 deletions documentation/src/main/asciidoc/introduction/Entities.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ There are two ways to apply a converter:
- the `@Convert` annotation applies an `AttributeConverter` to a particular entity attribute, or
- the `@Converter` annotation (or, alternatively, the `@ConverterRegistration` annotation) registers an `AttributeConverter` for automatic application to all attributes of a given type.

For example, the following converter will be automatically applied to any attribute of type `BitSet`, and takes care of persisting the `BitSet` to a column of type `varbinary`:
For example, the following converter will be automatically applied to any attribute of type `EnumSet<DayOfWeek>`, and takes care of persisting the `EnumSet<DayOfWeek>` to a column of type `INTEGER`:

[source,java]
----
Expand Down Expand Up @@ -687,9 +687,9 @@ On the other hand, if we _don't_ set `autoapply=true`, then we must explicitly a

[source,java]
----
@Convert(converter = BitSetConverter.class)
@Convert(converter = EnumSetConverter.class)
@Basic(optional = false)
BitSet bitset;
EnumSet<DayOfWeek> daysOfWeek;
----

All this is nice, but it probably won't surprise you that Hibernate goes beyond what is required by JPA.
Expand Down Expand Up @@ -738,7 +738,7 @@ Alternatively, the `@JavaTypeRegistration` annotation may be used to register `B
[discrete]
==== JdbcType

A `org.hibernate.type.descriptor.jdbc.JdbcType` is able to read and write a single Java type from and to JDBC.
An `org.hibernate.type.descriptor.jdbc.JdbcType` is able to read and write a single Java type from and to JDBC.

For example, `VarcharJdbcType` takes care of:

Expand Down Expand Up @@ -1233,7 +1233,7 @@ class Book {

Remember, if we wish to the modify the collection we must <<bidirectional-problem,change the owning side>>.

We've again used ``Set``s to represent the association.
We've again used `Set` to represent the association.
As before, we have the option to use `Collection` or `List`.
But in this case it _does_ make a difference to the semantics of the association.

Expand Down Expand Up @@ -1486,7 +1486,7 @@ Let's pause to remember the annotations we've met so far.
| Annotation | Purpose | JPA-standard

| `@GeneratedValue` | Specify that an identifier is system-generated | &#10004;
| `@SequenceGenerator` | Define an id generated backed by on a database sequence | &#10004;
| `@SequenceGenerator` | Define an id generated backed by a database sequence | &#10004;
| `@TableGenerator` | Define an id generated backed by a database table | &#10004;
| `@IdGeneratorType` | Declare an annotation that associates a custom `Generator` with each `@Id` attribute it annotates | &#10006;
| `@ValueGenerationType` | Declare an annotation that associates a custom `Generator` with each `@Basic` attribute it annotates | &#10006;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ interface Queries {
}
----

This gives some dynamic control over query execution, but what if would like direct control over the `Query` object?
This gives some dynamic control over query execution, but what if we would like direct control over the `Query` object?
Well, let's talk about the return type.

[[key-based-paging]]
Expand Down
24 changes: 13 additions & 11 deletions documentation/src/main/asciidoc/introduction/Interacting.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Session session = entityManager.unwrap(Session.class);
====

An instance of `Session` (or of `EntityManager`) is a _stateful session_.
It mediates the interaction between your program and the database via a operations on a _persistence context_.
It mediates the interaction between your program and the database via operations on a _persistence context_.

In this chapter, we're not going to talk much about `StatelessSession`.
We'll come back to <<stateless-sessions,this very useful API>> when we talk about performance.
Expand Down Expand Up @@ -576,9 +576,9 @@ session.getTransaction().commit();

A second way to reduce the cost of flushing is to load entities in _read-only_ mode:

- `Session.setDefaultReadOnly(false)` specifies that all entities loaded by a given session should be loaded in read-only mode by default,
- `SelectionQuery.setReadOnly(false)` specifies that every entity returned by a given query should be loaded in read-only mode, and
- `Session.setReadOnly(Object, false)` specifies that a given entity already loaded by the session should be switched to read-only mode.
- `Session.setDefaultReadOnly(true)` specifies that all entities loaded by a given session should be loaded in read-only mode by default,
- `SelectionQuery.setReadOnly(true)` specifies that every entity returned by a given query should be loaded in read-only mode, and
- `Session.setReadOnly(Object, true)` specifies that a given entity already loaded by the session should be switched to read-only mode.

It's not necessary to dirty-check an entity instance in read-only mode.

Expand Down Expand Up @@ -793,7 +793,7 @@ Execution of a criteria query works almost exactly like execution of HQL.
| Kind | `Session` method | `EntityManager` method | `Query` execution method

| Selection | `createSelectionQuery(CriteriaQuery)` | `createQuery(CriteriaQuery)` | `getResultList()`, `getSingleResult()`, or `getSingleResultOrNull()`
| Mutation | `createMutationQuery(CriteriaUpdate)` or `createQuery(CriteriaDelete)` | `createQuery(CriteriaUpdate)` or `createQuery(CriteriaDelte)` | `executeUpdate()`
| Mutation | `createMutationQuery(CriteriaUpdate)` or `createMutationQuery(CriteriaDelete)` | `createQuery(CriteriaUpdate)` or `createQuery(CriteriaDelte)` | `executeUpdate()`
|===

For example:
Expand Down Expand Up @@ -886,10 +886,12 @@ For the most simple cases, Hibernate can infer the shape of the result set:
----
Book book =
session.createNativeQuery("select * from Books where isbn = ?1", Book.class)
.setParameter(1, isbn)
.getSingleResult();
String title =
session.createNativeQuery("select title from Books where isbn = ?1", String.class)
.setParameter(1, isbn)
.getSingleResult();
----

Expand All @@ -905,7 +907,7 @@ So if there are any unflushed changes to ``Book``s, this query might return stal
----
List<Book> books =
session.createNativeQuery("select * from Books", Book.class)
.getResultList()
.getResultList();
----

There's two ways to ensure the persistence context is flushed before this query is executed.
Expand All @@ -917,7 +919,7 @@ Either, we could simply force a flush by calling `flush()` or by setting the flu
List<Book> books =
session.createNativeQuery("select * from Books", Book.class)
.setHibernateFlushMode(ALWAYS)
.getResultList()
.getResultList();
----

Or, alternatively, we could tell Hibernate which modified state affects the results of the query:
Expand All @@ -927,7 +929,7 @@ Or, alternatively, we could tell Hibernate which modified state affects the resu
List<Book> books =
session.createNativeQuery("select * from Books", Book.class)
.addSynchronizedEntityClass(Book.class)
.getResultList()
.getResultList();
----

[TIP]
Expand Down Expand Up @@ -995,7 +997,7 @@ The `getResultCount()` method is useful for displaying the number of pages of re
SelectionQuery<Book> query =
session.createSelectionQuery("from Book where title like ?1 order by title", Book.class)
.setParameter(1, titlePattern);
long pages = query.getResultCount() / MAX_RESULTS;
long pages = (long) Math.ceil(query.getResultCount() * 1.0 / MAX_RESULTS);
List<Book> books = query.setMaxResults(MAX_RESULTS).getResultList();
----

Expand Down Expand Up @@ -1061,7 +1063,7 @@ if (!firstPage.isLastPage()) {
----

The "key" in key-based pagination refers to a unique key of the result set which determines a total order on the query results.
In this example, `Book.isbn` is the key.
In this example, `Book_.isbn` is the key.

Since this code is a little bit fiddly, key-based pagination works best with <<key-based-paging,generated query or finder methods>>.

Expand Down Expand Up @@ -1121,7 +1123,7 @@ var bookIsbn = book.get(Book_.isbn);
var bookPrice = book.get(Book_.price);
query.select(builder.tuple(bookTitle, bookIsbn, bookPrice));
var resultList = session.createSelectionQuery(query).getResultList();
for (var result: resultList) {
for (var result : resultList) {
String title = result.get(bookTitle);
String isbn = result.get(bookIsbn);
BigDecimal price = result.get(bookPrice);
Expand Down
16 changes: 8 additions & 8 deletions documentation/src/main/asciidoc/introduction/Introduction.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Hibernate makes *relational data* visible to a program written in Java, in a *na
3. allowing performance optimizations to be made after the basic persistence logic has already been written.
****

Here the relational data is the focus, along with the importance of typesafety.
Here the relational data is the focus, along with the importance of type safety.
The goal of _object/relational mapping_ (ORM) is to eliminate fragile and untypesafe code, and make large programs easier to maintain in the long run.

ORM takes the pain out of persistence by relieving the developer of the need to hand-write tedious, repetitive, and fragile code for flattening graphs of objects to database tables and rebuilding graphs of objects from flat SQL query result sets.
Expand Down Expand Up @@ -409,7 +409,7 @@ public class Main {
In practice, we never access the database directly from a `main()` method.
So now let's talk about how to organize persistence logic in a real system.
The rest of this chapter is not compulsory.
If you're itching for more details about Hibernate itself, you're quite welcome to skip straight to the <<entities,next chapter>>, and come back later.
If you're itching for more details about Hibernate itself, you're quite welcome to skip straight to the <<configuration,next chapter>>, and come back later.

[[organizing-persistence]]
=== Organizing persistence logic
Expand Down Expand Up @@ -462,7 +462,7 @@ Let's now consider a slightly more complicated case.
----
@Path("/") @Produces("application/json")
public class BookResource {
private static final RESULTS_PER_PAGE = 20;
private static final int RESULTS_PER_PAGE = 20;
@GET @Path("books/{titlePattern}/{page:\\d+}")
public List<Book> findBooks(String titlePattern, int page) {
Expand Down Expand Up @@ -497,10 +497,10 @@ static List<Book> findBooksByTitleWithPagination(Session session,
This is an example of a _query method_, a function which accepts arguments to the parameters of a HQL or SQL query, and executes the query, returning its results to the caller.
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.
It's even better to specify the query string using the `@NamedQuery` annotation, so that Hibernate can validate the query 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:
We need a place to put the annotation, so let's move our query method to a new class:

[source,java]
----
Expand Down Expand Up @@ -614,7 +614,7 @@ We do need to be careful here if our persistence code uses native SQL, or if it
====

Whether we're testing against our real database, or against an in-memory Java database, we'll need to export the schema at the beginning of a test suite.
We _usually_ do this when we create the Hibernate `SessionFactory` or JPA `EntityManager`, and so traditionally we've used a <<automatic-schema-export,configuration property>> for this.
We _usually_ do this when we create the Hibernate `SessionFactory` or JPA `EntityManagerFactory`, and so traditionally we've used a <<automatic-schema-export,configuration property>> for this.

The JPA-standard property is `jakarta.persistence.schema-generation.database.action`.
For example, if we're using `Configuration` to configure Hibernate, we could write:
Expand Down Expand Up @@ -686,7 +686,7 @@ Then testing persistence logic is now straightforward!

You'll need to:

- bootstrap Hibernate and create a `SessionFactory` or `EntityManagerFactory` and the beginning of your test suite (we've already seen how to do that), and
- bootstrap Hibernate and create a `SessionFactory` or `EntityManagerFactory` at the beginning of your test suite (we've already seen how to do that), and
- create a new `Session` or `EntityManager` inside each `@Test` method, using `inTransaction()`, for example.

Actually, some tests might require multiple sessions.
Expand Down Expand Up @@ -718,7 +718,7 @@ Let's now consider a different approach to code organization, one we treat with
[WARNING]
====
In this section, we're going to give you our _opinion_.
If you're only interested in facts, or if you prefer not to read things that might undermine the opinion you currently hold, please feel free to skip straight to the <<entities,next chapter>>.
If you're only interested in facts, or if you prefer not to read things that might undermine the opinion you currently hold, please feel free to skip straight to the <<configuration,next chapter>>.
====

Hibernate is an architecture-agnostic library, not a framework, and therefore integrates comfortably with a wide range of Java frameworks and containers.
Expand Down
4 changes: 2 additions & 2 deletions documentation/src/main/asciidoc/introduction/Mapping.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ In principle, the `Blob` and `Clob` objects provide efficient ways to read or st
----
Book book = session.find(Book.class, bookId);
String text = book.text.getSubString(1, textLength);
InputStream bytes = book.images.getBinaryStream();
InputStream bytes = book.coverArt.getBinaryStream();
----

Of course, the behavior here depends very much on the JDBC driver, and so we really can't promise that this is a sensible thing to do on your database.
Expand Down Expand Up @@ -1035,7 +1035,7 @@ But it's common to need to:

We've <<join-column-mappings,already seen>> how to use `@ForeignKey` to specify the name of a foreign key constraint.

There's two ways to add a unique constraint to a table:
There are two ways to add a unique constraint to a table:

- using `@Column(unique=true)` to indicate a single-column unique key, or
- using the `@UniqueConstraint` annotation to define a uniqueness constraint on a combination of columns.
Expand Down
4 changes: 2 additions & 2 deletions documentation/src/main/asciidoc/introduction/Tuning.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ hibernate.agroal.reapTimeout PT10s
----

As long as you set at least one property with the prefix `hibernate.agroal`, the `AgroalConnectionProvider` will be selected automatically.
There's many to choose from:
There are many to choose from:

.Settings for configuring Agroal
[%breakable,cols="37,~"]
Expand Down Expand Up @@ -583,7 +583,7 @@ If there are multiple implementations on the classpath, we must disambiguate usi
|===
| Configuration property name | Property value

| `hibernate.javax.cache.provider` a| The implementation of `javax.cache.spiCachingProvider`, for example:
| `hibernate.javax.cache.provider` a| The implementation of `javax.cache.spi.CachingProvider`, for example:
[%breakable,cols="~,20"]
!===
! `org.ehcache.jsr107.EhcacheCachingProvider` ! for EHCache
Expand Down

0 comments on commit c4a60fb

Please sign in to comment.