copy configuration section from HR intro

This commit is contained in:
Gavin 2023-05-07 14:00:24 +02:00 committed by Gavin King
parent 42819dd6f9
commit deb19d02d0
1 changed files with 315 additions and 1 deletions

View File

@ -20,5 +20,319 @@ The fourth option is extremely popular, since every major Java application serve
Such container environments also typically feature facilities to automatically manage the lifecycle of an `EntityManager` or `Session` and its association with container-managed transactions.
To learn how to configure Hibernate in such a container environment, you'll need to refer to the documentation of your chosen container.
[[required-dependencies]]
=== Including Hibernate in your project build
If you're using Hibernate outside of a container environment,
you'll need to:
- include Hibernate ORM itself, along with the appropriate JDBC driver, as dependencies of your project, and
- configure Hibernate with information about your database,
by specifying configuration properties.
First, add the following dependency to your project:
----
org.hibernate.orm:hibernate-core:{version}
----
Where `{version}` is the version of Hibernate you're using.
You'll also need to add a dependency for the JDBC
driver for your database.
|===
| Database | Driver dependency
| PostgreSQL or CockroachDB | `org.postgresql:postgresql:{version}`
| MySQL | `mysql:mysql-connector-java:{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:ojdbc8:${version}`
| h2 | `com.h2database:h2:{version}`
|===
Where `{version}` is the latest version of the JDBC driver for your databse.
[[optional-dependencies]]
=== Optional dependencies
:slf4j: http://www.slf4j.org/
:enhancer: https://docs.jboss.org/hibernate/orm/5.4/topical/html_single/bytecode/BytecodeEnhancement.html
Optionally, you might also add any of the following additional features:
|===
| Optional feature | Dependencies
| An {slf4j}[SLF4J] logging implementation | `org.apache.logging.log4j:log4j-core` or `org.slf4j:slf4j-jdk14`
| The Hibernate metamodel generator, if you're using the JPA criteria query API | `org.hibernate.orm:hibernate-jpamodelgen`
| Hibernate Validator | `org.hibernate.validator:hibernate-validator` and `org.glassfish:jakarta.el`
| Compile-time checking for your HQL queries | `org.hibernate:query-validator`
| Second-level cache support via JCache and EHCache | `org.hibernate.orm:hibernate-jcache` along with `org.ehcache:ehcache`
// | SCRAM authentication support for PostgreSQL | `com.ongres.scram:client:2.1`
|===
You might also add the Hibernate {enhancer}[bytecode enhancer] to your
Gradle build if you want to use field-level lazy fetching.
TIP: Field-level lazy fetching is an advanced feature that most programs
don't need. Stick to the basics for now.
[[configuration-jpa]]
=== Configuration using JPA
=== Configuration using JPA XML
Sticking to the JPA-standard approach, we would provide a file named `persistence.xml`, which we usually place in the `META-INF` directory of a _persistence archive_, that is, of the `.jar` file or directory which contains our entity classes.
[source,xml]
----
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="2.0">
<persistence-unit name="org.hibernate.example">
<class>org.hibernate.example.Book</class>
<class>org.hibernate.example.Author</class>
<properties>
<!-- PostgreSQL -->
<property name="jakarta.persistence.jdbc.url"
value="jdbc:postgresql://localhost/example"/>
<!-- Credentials -->
<property name="jakarta.persistence.jdbc.user"
value="gavin"/>
<property name="jakarta.persistence.jdbc.password"
value="hibernate"/>
<!-- Automatic schema export -->
<property name="jakarta.persistence.schema-generation.database.action"
value="drop-and-create"/>
<!-- SQL statement logging -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.highlight_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
----
The `<persistence-unit>` element defines a named _persistence unit_, that is:
- a collection of associated entity types, along with
- a set of default configuration settings, which may be augmented or overridden at runtime.
Each `<class>` element specifies the fully-qualified name of an entity class.
[TIP]
.Scanning for entity classes
====
In some container environments, for example, in any EE container, the `<class>` elements are unnecessary, since the container will scan the archive for annotated classes, and automatically recognize any class annotated `@Entity`.
====
Each `<property>` element specifies a _configuration property_ and its value:
- the configuration properties in the `jakarta.persistence` namespace are standard properties defined by the JPA spec, and
- properties in the `hibernate` namespace are defined by Hibernate.
We may obtain an `EntityManagerFactory` by calling `Persistence.createEntityManagerFactory()`:
[source,java]
----
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("org.hibernate.example");
----
If necessary, we may override configuration properties specified in `persistence.xml`:
[source,java]
----
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("org.hibernate.example",
Map.of(AvailableSettings.JAKARTA_JDBC_PASSWORD, password));
----
[[configuration-api]]
=== Configuration using Hibernate API
Alternatively, the venerable class `org.hibernate.cfg.Configuration` allows an instance of Hibernate to be configured in Java code:
[source,java]
----
SessionFactory factory = new Configuration()
.addAnnotatedClass(Book.class)
.addAnnotatedClass(Author.class)
.setProperty(AvailableSettings.JAKARTA_JDBC_URL, "jdbc:postgresql://localhost/example")
.setProperty(AvailableSettings.JAKARTA_JDBC_USER, user)
.setProperty(AvailableSettings.JAKARTA_JDBC_PASSWORD, password)
.setProperty(AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.CREATE)
.setProperty(AvailableSettings.SHOW_SQL, true)
.setProperty(AvailableSettings.FORMAT_SQL, true)
.setProperty(AvailableSettings.HIGHLIGHT_SQL, true)
.buildSessionFactory();
----
The `Configuration` class has survived almost unchanged since the very earliest (pre-1.0) versions of Hibernate, and so it doesn't look particularly modern.
On the other hand, it's very easy to use, and exposes some options that `persistence.xml` doesn't support.
[TIP]
.Advanced configuration options
====
Actually, the `Configuration` class is just a very simple facade for the more modern, much more powerful&mdash;but more complex&mdash;API defined in the package `org.hibernate.boot`.
This API is useful if you have very advanced requirements, for example, if you're writing a framework or implementing a container.
You'll find more information in the Hibernate ORM Integration Guide, and in the package-level documentation of `org.hibernate.boot`.
====
[[basic-configuration-settings]]
=== Basic configuration settings
The class `org.hibernate.cfg.AvailableSettings` enumerates all the configuration properties understood by Hibernate.
[TIP]
.You ain't gunna need 'em
====
Hibernate has many&mdash;too many&mdash;switches and toggles.
Please don't go crazy messing about with these settings; most of them are rarely needed, and many only exist to provide backward compatibility with older versions of Hibernate.
With rare exception, the default behavior of every one of these settings was carefully chosen to be _the behavior we recommend_.
====
The properties you do need to get started are these three:
|===
| Configuration property name | Purpose
| `jakarta.persistence.jdbc.url` | JDBC URL of your database
| `jakarta.persistence.jdbc.user` and `jakarta.persistence.jdbc.password` | Your database credentials
|===
[IMPORTANT]
.You don't need `hibernate.dialect` anymore!
====
In Hibernate 6, you don't need to specify `hibernate.dialect`.
The correct Hibernate SQL `Dialect` will be determined for you.
The only reason to specify this property is if you're using a custom user-written `Dialect` class.
====
[[automatic-schema-export]]
=== Automatic schema export
You can have Hibernate infer your database schema from the mapping
annotations you've specified in your Java code, and export the schema at
initialization time by specifying one or more of the following configuration
properties:
[cols="1,1"]
|===
| Configuration property name | Purpose
| `jakarta.persistence.schema-generation.database.action`
a| * If `drop-and-create`, first drop the schema and then export tables, sequences, and constraints.
* If `create`, export tables, sequences, and constraints, without attempting to drop them first.
* If `create-drop`, drop the schema and recreate it on `SessionFactory` startup.
Additionally, drop the schema on `SessionFactory` shutdown.
* If `drop`, drop the schema on `SessionFactory` shutdown.
* If `validate`, validate the database schema without changing it.
* If `update`, only export what's missing in the schema.
| `jakarta.persistence.create-database-schemas`
| (Optional) If `true`, automatically create schemas and catalogs
| `jakarta.persistence.schema-generation.create-source`
| (Optional) If `metadata-then-script` or `script-then-metadata`, execute an additional SQL script when exported tables and sequences
| `jakarta.persistence.schema-generation.create-script-source`
| (Optional) The name of the SQL script to be executed
|===
This feature is extremely useful for testing.
[TIP]
.Importing test or reference data
====
The easiest way to pre-initialize a database with test or "reference" data is to place a list of SQL `insert` statements in a file named, for example, `import.sql`, and specify the path to this file using the property `jakarta.persistence.schema-generation.create-script-source`.
This approach is cleaner than writing Java code to instantiate entity instances and calling `persist()` on each of them.
====
[TIP]
.Programmatic schema export
====
The `SchemaManager` API allow you to control schema export programmatically.
====
=== Logging the generated SQL
:log4j: https://github.com/hibernate/hibernate-reactive/blob/main/examples/session-example/src/main/resources/log4j2.properties
To see the generated SQL as it's sent to the database, either:
- set the property `hibernate.show_sql` to `true`, or
- enable debug-level logging for the category `org.hibernate.SQL`
using your preferred SLF4J logging implementation.
For example, if you're using Log4J 2 (as above in <<optional-dependencies>>),
add these lines to your `log4j2.properties` file:
[source,properties]
----
logger.hibernate.name = org.hibernate.SQL
logger.hibernate.level = debug
----
You can make the logged SQL more readable by enabling one or both of
the following settings:
|===
| Configuration property name | Purpose
| `hibernate.format_sql` | If `true`, log SQL in a multiline, indented format
| `hibernate.highlight_sql` | If `true`, log SQL with syntax highlighting via ANSI escape codes
|===
=== Minimizing repetitive mapping information
The following properties are very useful for minimizing the amount of
information you'll need to explicitly specify in `@Table` and `@Column`
annotations which we'll discuss below in <<mapping-entity-classes>>:
|===
| Configuration property name | Purpose
| `hibernate.default_schema` | A default schema name for entities which do not explicitly declare one
| `hibernate.default_catalog` | A default catalog name for entities which do not explicitly declare one
| `hibernate.physical_naming_strategy` | A `PhysicalNamingStrategy` implementing your database naming standards
|===
[TIP]
.Implement your naming standards as a `PhysicalNamingStrategy`
====
Writing your own `PhysicalNamingStrategy` is an especially good
way to reduce the clutter of annotations on your entity classes, and
we think you should do it for any nontrivial data model.
====
=== Nationalized character data in SQL Server
_By default,_ SQL Server's `char` and `varchar` types don't accommodate
Unicode data. So, if you're working with SQL Server, you might need to
force Hibernate to use the `nchar` and `nvarchar` types.
|===
| Configuration property name | Purpose
| `hibernate.use_nationalized_character_data` | Use `nchar` and `nvarchar` instead of `char` and `varchar`
|===
[TIP]
.Configuring SQL Server to use UTF-8 by default
====
Alternatively, you can configure SQL Server to use the UTF-8 enabled collation `_UTF8`.
====