HHH-18588 fix minor defects in Hibernate Introduction doc
This commit is contained in:
parent
2ada4ac8e4
commit
c4a60fbe4c
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 | ✔
|
||||
| `@SequenceGenerator` | Define an id generated backed by on a database sequence | ✔
|
||||
| `@SequenceGenerator` | Define an id generated backed by a database sequence | ✔
|
||||
| `@TableGenerator` | Define an id generated backed by a database table | ✔
|
||||
| `@IdGeneratorType` | Declare an annotation that associates a custom `Generator` with each `@Id` attribute it annotates | ✖
|
||||
| `@ValueGenerationType` | Declare an annotation that associates a custom `Generator` with each `@Basic` attribute it annotates | ✖
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue