From b77d5bd3b85690b1939d4ec2209f71069036e4d1 Mon Sep 17 00:00:00 2001 From: Gavin Date: Sun, 7 May 2023 14:00:24 +0200 Subject: [PATCH] copy configuration section from HR intro --- .../asciidoc/introduction/Configuration.adoc | 316 +++++++++++++++++- 1 file changed, 315 insertions(+), 1 deletion(-) diff --git a/documentation/src/main/asciidoc/introduction/Configuration.adoc b/documentation/src/main/asciidoc/introduction/Configuration.adoc index 5a5ffd77f6..1d8b41bf6a 100644 --- a/documentation/src/main/asciidoc/introduction/Configuration.adoc +++ b/documentation/src/main/asciidoc/introduction/Configuration.adoc @@ -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] +---- + + + + + org.hibernate.example.Book + org.hibernate.example.Author + + + + + + + + + + + + + + + + + + + + + + +---- +The `` 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 `` 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 `` elements are unnecessary, since the container will scan the archive for annotated classes, and automatically recognize any class annotated `@Entity`. +==== + +Each `` 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—but more complex—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—too many—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 <>), +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 <>: + +|=== +| 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`. +==== \ No newline at end of file