HHH-18588 fix minor defects in Hibernate Introduction doc

This commit is contained in:
nathan.xu 2024-09-09 09:49:05 -04:00
parent 2ada4ac8e4
commit c4a60fbe4c
8 changed files with 40 additions and 38 deletions

View File

@ -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

View File

@ -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()`
@ -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
@ -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,~"]
@ -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.

View File

@ -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]
----
@ -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.
@ -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:
@ -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.
@ -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;

View File

@ -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]]

View File

@ -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.
@ -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.
@ -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:
@ -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();
----
@ -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.
@ -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:
@ -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]
@ -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();
----
@ -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>>.
@ -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);

View File

@ -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.
@ -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
@ -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) {
@ -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]
----
@ -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:
@ -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.
@ -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.

View File

@ -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.
@ -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.

View File

@ -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,~"]
@ -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