update the QuickStart guide (#6807)
* update the code examples in the quickstart * update the quickstart document * slightly restructure the quickstart document
This commit is contained in:
parent
126207bbfe
commit
7cf4fd0626
|
@ -114,7 +114,7 @@ tasks.register('renderTopicalGuides', AsciidoctorTask) { task ->
|
|||
|
||||
tasks.register('renderGettingStartedGuides', AsciidoctorTask) { task ->
|
||||
group = "Documentation"
|
||||
description = 'Renders the Getting Started Guides (quick starts) in HTML format using Asciidoctor.'
|
||||
description = 'Renders the Getting Started Guides (quickstarts) in HTML format using Asciidoctor.'
|
||||
tasks.buildDocs.dependsOn task
|
||||
tasks.buildDocsForPublishing.dependsOn task
|
||||
inputs.property "hibernate-version", project.ormVersion
|
||||
|
@ -124,8 +124,41 @@ tasks.register('renderGettingStartedGuides', AsciidoctorTask) { task ->
|
|||
include 'index.adoc'
|
||||
}
|
||||
outputDir = new File("$buildDir/asciidoc/quickstart/html_single")
|
||||
|
||||
attributes linkcss: true,
|
||||
stylesheet: "css/hibernate.css",
|
||||
docinfo: 'private',
|
||||
jpaJavadocUrlPrefix: "https://javaee.github.io/javaee-spec/javadocs/javax/persistence/"
|
||||
|
||||
resources {
|
||||
from('src/main/style/asciidoctor') {
|
||||
include 'images/**'
|
||||
}
|
||||
from('src/main/style/asciidoctor') {
|
||||
include 'css/**'
|
||||
}
|
||||
from('src/main/style/asciidoctor') {
|
||||
include 'js/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('renderGettingStartedGuidesPdf', AsciidoctorPdfTask) {task->
|
||||
group = "Documentation"
|
||||
description = 'Renders the Getting Started Guides in PDF format using Asciidoctor.'
|
||||
tasks.buildDocs.dependsOn task
|
||||
tasks.buildDocsForPublishing.dependsOn task
|
||||
inputs.property "hibernate-version", project.ormVersion
|
||||
|
||||
sourceDir = file( 'src/main/asciidoc/quickstart/guides' )
|
||||
baseDir = file( 'src/main/asciidoc/quickstart/guides' )
|
||||
sources {
|
||||
include 'index.adoc'
|
||||
}
|
||||
outputDir = "$buildDir/asciidoc/quickstart/pdf"
|
||||
|
||||
attributes jpaJavadocUrlPrefix: "https://javaee.github.io/javaee-spec/javadocs/javax/persistence/"
|
||||
}
|
||||
|
||||
tasks.register('buildTutorialZip', Zip) { task ->
|
||||
from 'src/main/asciidoc/quickstart/tutorials'
|
||||
|
@ -133,7 +166,7 @@ tasks.register('buildTutorialZip', Zip) { task ->
|
|||
archiveFileName = 'hibernate-tutorials.zip'
|
||||
expand(
|
||||
version: project.version,
|
||||
slf4j: "1.7.5",
|
||||
slf4j: "2.0.7",
|
||||
junit: testLibs.versions.junit4.get(),
|
||||
h2: dbLibs.versions.h2.get()
|
||||
)
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
= Hibernate Getting Started Guide
|
||||
:pdf-theme: ../../pdf/theme.yml
|
||||
:source-highlighter: rouge
|
||||
:icons: font
|
||||
:doctype: book
|
||||
:pdf-fontsdir: ../../pdf/fonts
|
||||
|
||||
= Getting Started with Hibernate
|
||||
:title-logo-image: image:../../../style/asciidoctor/images/org/hibernate/logo.png[]
|
||||
:toc:
|
||||
:docinfo:
|
||||
|
||||
include::preface.adoc[]
|
||||
|
||||
:numbered:
|
||||
include::obtaining.adoc[]
|
||||
|
||||
include::tutorial_native.adoc[]
|
||||
|
||||
include::tutorial_annotations.adoc[]
|
||||
|
||||
include::tutorial_jpa.adoc[]
|
||||
|
|
|
@ -1,54 +1,109 @@
|
|||
[[introduction]]
|
||||
== Introduction
|
||||
|
||||
Hibernate is an _Object/Relational Mapping_ (ORM) solution for programs written in Java and other JVM languages.
|
||||
It lets us map Java classes to database tables, and fields of the Java classes to columns of the tables, and then
|
||||
takes over the most tedious work involved in executing SQL statements against the database. Hibernate typically
|
||||
eliminates upward of 90% of the work involved in common persistence-related programming tasks.
|
||||
|
||||
However, unlike some other persistence solutions, Hibernate doesn't attempt to hide the relational model, nor take
|
||||
away the power of SQL as a query language. On the contrary, Hibernate centers the relational data, makes it visible
|
||||
to Java in a natural and typesafe object-oriented form, and offers an extremely powerful SQL-like query language for
|
||||
working with the data in Java.
|
||||
|
||||
[NOTE]
|
||||
Hibernate may not be the best solution for data-centric applications where business logic is implemented in stored
|
||||
procedures. Hibernate is most useful for programs with an object-oriented domain model and business logic in a
|
||||
Java-based _middle tier_.
|
||||
|
||||
[[resources]]
|
||||
.Resources
|
||||
****
|
||||
A strong background in SQL is not required to use Hibernate, at least not at first, but a basic understanding of the
|
||||
concepts is important.
|
||||
An understanding of _data modeling_ principles is especially important.
|
||||
Good starting points include:
|
||||
|
||||
- https://www.agiledata.org/essays/dataModeling101.html[Data Modeling 101], and
|
||||
- https://en.wikipedia.org/wiki/Data_modeling[Wikipedia].
|
||||
|
||||
If you're completely new to database access in Java, a decent overview of various technologies and options and how they
|
||||
fit together may be found at:
|
||||
|
||||
- https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java[Java & Databases: An Overview of Libraries & APIs].
|
||||
|
||||
This guide will help you get up and running with Hibernate itself.
|
||||
But the best way to start learning Hibernate properly is the _Introduction to Hibernate 6_, available at
|
||||
https://hibernate.org/orm/documentation[the same place you got this document].
|
||||
|
||||
[TIP]
|
||||
====
|
||||
Of course, the other essential resource will be the documentation for your RDBMS, and especially the guide to the dialect
|
||||
of SQL provided by your database.
|
||||
====
|
||||
****
|
||||
|
||||
[[obtaining]]
|
||||
== Obtaining Hibernate
|
||||
=== Obtaining Hibernate
|
||||
|
||||
=== The Hibernate Modules/Artifacts
|
||||
We may obtain any Hibernate module we need just by declaring a dependency on the module in our Maven or Gradle build.
|
||||
We're certainly going to need `hibernate-core`, so we'll go ahead and declare a dependency on `org.hibernate.orm:hibernate-core`.
|
||||
|
||||
Hibernate's functionality is split into a number of modules/artifacts meant to isolate dependencies (modularity).
|
||||
In Gradle we would have:
|
||||
|
||||
hibernate-core:: The main (core) Hibernate module. Defines its ORM features and APIs as well as the various integration SPIs.
|
||||
hibernate-envers:: Hibernate's historical entity versioning feature
|
||||
hibernate-spatial:: Hibernate's Spatial/GIS data-type support
|
||||
hibernate-agroal:: Integrates the https://agroal.github.io/[Agroal] connection pooling library into Hibernate
|
||||
hibernate-c3p0:: Integrates the https://www.mchange.com/projects/c3p0/[C3P0] connection pooling library into Hibernate
|
||||
hibernate-hikaricp:: Integrates the https://github.com/brettwooldridge/HikariCP/[HikariCP] connection pooling library into Hibernate
|
||||
hibernate-vibur:: Integrates the https://www.vibur.org/[Vibur DBCP] connection pooling library into Hibernate
|
||||
hibernate-proxool:: Integrates the https://proxool.sourceforge.net/[Proxool] connection pooling library into Hibernate
|
||||
hibernate-jcache:: Integrates the https://jcp.org/en/jsr/detail?id=107$$[JCache] caching specification into Hibernate,
|
||||
enabling any compliant implementation to become a second-level cache provider.
|
||||
hibernate-community-dialects:: Hibernate's community supported dialects
|
||||
hibernate-graalvm:: Experimental extension to make it easier to compile applications into a https://www.graalvm.org/[GraalVM] native image
|
||||
hibernate-micrometer:: Integration for Micrometer metrics into Hibernate as a metrics collection package
|
||||
hibernate-testing:: Support for testing Hibernate ORM functionality
|
||||
hibernate-integrationtest-java-modules:: Integration tests for running Hibernate ORM in the Java module path
|
||||
[source,groovy]
|
||||
----
|
||||
implementation 'org.hibernate.orm:hibernate-core:6.3.0.Final'
|
||||
----
|
||||
|
||||
=== Release Bundle Downloads
|
||||
Or in Maven:
|
||||
|
||||
The Hibernate team provides release bundles hosted on the SourceForge File Release System, in both
|
||||
`TGZ` and `ZIP` formats. Each release bundle contains `JAR` files, documentation, source code, and other goodness.
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.hibernate.org</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>6.3.0.Final</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
You can download releases of Hibernate, in your chosen format, from the list at
|
||||
https://sourceforge.net/projects/hibernate/files/hibernate-orm/. The release bundle is structured as follows:
|
||||
[[modules]]
|
||||
=== Modules belonging to Hibernate ORM
|
||||
|
||||
* The `lib/required/` directory contains the `hibernate-core` jar and all of its dependencies. All of these jars are
|
||||
required to be available on your classpath no matter which features of Hibernate are being used.
|
||||
* The `lib/envers` directory contains the `hibernate-envers` jar and all of its dependencies (beyond those in
|
||||
`lib/required/` and `lib/jpa/`).
|
||||
* The `lib/spatial/` directory contains the `hibernate-spatial` jar and all of its dependencies (beyond those in `lib/required/`)
|
||||
* The `lib/jpa-metamodel-generator/` directory contains the jar needed for generating the Criteria API type-safe Metamodel.
|
||||
* The `lib/optional/` directory contains the jars needed for the various connection pooling and second-level cache integrations
|
||||
provided by Hibernate, along with their dependencies.
|
||||
Hibernate ORM is an umbrella project containing the following modules:
|
||||
|
||||
=== Maven Repository Artifacts
|
||||
[cols="40m,~"]
|
||||
.API-oriented modules
|
||||
|===
|
||||
|hibernate-core| The core object/relational mapping engine
|
||||
|hibernate-envers| Entity versioning and auditing
|
||||
|hibernate-spatial| Support for spatial/GIS data types
|
||||
|hibernate-jpamodelgen| An annotation processor that generates a JPA-compliant metamodel
|
||||
|===
|
||||
|
||||
The authoritative repository for Hibernate artifacts is the JBoss Maven repository. The Hibernate artifacts are
|
||||
synced to Maven Central as part of an automated job (some small delay may occur).
|
||||
[cols="40m,~"]
|
||||
.Integration-oriented modules
|
||||
|===
|
||||
|hibernate-agroal| Support for https://agroal.github.io/[Agroal] connection pooling
|
||||
|hibernate-c3p0| Support for https://www.mchange.com/projects/c3p0/[C3P0] connection pooling
|
||||
|hibernate-hikaricp| Support for https://github.com/brettwooldridge/HikariCP/[HikariCP] connection pooling
|
||||
|hibernate-vibur| Support for https://www.vibur.org/[Vibur DBCP] connection pooling
|
||||
|hibernate-proxool| Support for https://proxool.sourceforge.net/[Proxool] connection pooling
|
||||
|hibernate-jcache| Integration with https://jcp.org/en/jsr/detail?id=107$$[JCache], allowing any compliant implementation as a second-level cache provider
|
||||
|hibernate-community-dialects| Additional community-supported SQL dialects
|
||||
|hibernate-graalvm| Experimental extension to make it easier to compile applications as a https://www.graalvm.org/[GraalVM] native image
|
||||
|hibernate-micrometer| Integration with https://micrometer.io[Micrometer] metrics
|
||||
|===
|
||||
|
||||
The team responsible for the JBoss Maven repository maintains a number of Wiki pages that contain important information:
|
||||
[cols="40m,~"]
|
||||
.Testing-oriented modules
|
||||
|===
|
||||
|hibernate-testing| A framework for testing Hibernate ORM functionality
|
||||
|hibernate-integrationtest-java-modules| Integration tests for running Hibernate ORM in the Java module path
|
||||
|===
|
||||
|
||||
* https://community.jboss.org/docs/DOC-14900 - General information about the repository.
|
||||
* https://community.jboss.org/docs/DOC-15170 - Information about setting up the JBoss repositories in order to do
|
||||
development work on JBoss projects themselves.
|
||||
* https://community.jboss.org/docs/DOC-15169 - Information about setting up access to the repository to use JBoss
|
||||
projects as part of your own software.
|
||||
These artifacts are published under the Maven group id `org.hibernate.orm`.
|
||||
|
||||
[NOTE]
|
||||
There's more to Hibernate than the modules belonging to the ORM project: Hibernate Search, Hibernate Reactive, Hibernate Validator, and more.
|
||||
|
||||
The Hibernate ORM artifacts are published under the `org.hibernate` groupId.
|
|
@ -1,38 +0,0 @@
|
|||
[[preface]]
|
||||
|
||||
[preface]
|
||||
== Preface
|
||||
|
||||
Working with both Object-Oriented software and Relational Databases can be cumbersome and time-consuming.
|
||||
Development costs are significantly higher due to a number of "paradigm mismatches" between how data is represented in objects
|
||||
versus relational databases. Hibernate is an Object/Relational Mapping (ORM) solution for Java environments. The
|
||||
term Object/Relational Mapping refers to the technique of mapping data between an object model representation to
|
||||
a relational data model representation. See https://en.wikipedia.org/wiki/Object-relational_mapping for a good
|
||||
high-level discussion. Also, Martin Fowler's link:$$https://martinfowler.com/bliki/OrmHate.html$$[OrmHate] article
|
||||
takes a look at many of the mismatch problems.
|
||||
|
||||
Although having a strong background in SQL is not required to use Hibernate, having a basic understanding of the
|
||||
concepts can help you understand Hibernate more quickly and fully. An understanding of data modeling principles
|
||||
is especially important. Both https://www.agiledata.org/essays/dataModeling101.html and
|
||||
https://en.wikipedia.org/wiki/Data_modeling are good starting points for understanding these data modeling
|
||||
principles. If you are completely new to database access in Java,
|
||||
https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java contains a good overview of the various parts,
|
||||
pieces and options.
|
||||
|
||||
Hibernate takes care of the mapping from Java classes to database tables, and from Java data types to SQL data
|
||||
types. In addition, it provides data query and retrieval facilities. It can significantly reduce development
|
||||
time otherwise spent with manual data handling in SQL and JDBC. Hibernate’s design goal is to relieve the
|
||||
developer from 95% of common data persistence-related programming tasks by eliminating the need for manual,
|
||||
hand-crafted data processing using SQL and JDBC. However, unlike many other persistence solutions, Hibernate
|
||||
does not hide the power of SQL from you and guarantees that your investment in relational technology and
|
||||
knowledge is as valid as always.
|
||||
|
||||
Hibernate may not be the best solution for data-centric applications that only use stored-procedures to
|
||||
implement the business logic in the database, it is most useful with object-oriented domain models and business
|
||||
logic in the Java-based middle-tier. However, Hibernate can certainly help you to remove or encapsulate
|
||||
vendor-specific SQL code and streamlines the common task of translating result sets from a tabular
|
||||
representation to a graph of objects.
|
||||
|
||||
See https://hibernate.org/orm/contribute/ for information on getting involved.
|
||||
|
||||
IMPORTANT: The projects and code for the tutorials referenced in this guide are available as link:hibernate-tutorials.zip[]
|
|
@ -1,104 +1,208 @@
|
|||
[[tutorial_annotations]]
|
||||
== Tutorial Using Native Hibernate APIs and Annotation Mappings
|
||||
|
||||
NOTE: This tutorial is located within the download bundle under `annotations/`.
|
||||
== Tutorial using native Hibernate APIs
|
||||
|
||||
.Objectives
|
||||
- [*] Bootstrap a Hibernate `SessionFactory`
|
||||
- [*] Configure Hibernate using `hibernate.properties`
|
||||
- [*] Create a `SessionFactory` using `org.hibernate.boot`
|
||||
- [*] Use annotations to provide mapping information
|
||||
- [*] Use the Hibernate native APIs
|
||||
- [*] Use `Session` to persist and query data
|
||||
|
||||
|
||||
****
|
||||
This tutorial is located within the download bundle under `annotations/`.
|
||||
****
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-config]]
|
||||
=== The Hibernate configuration file
|
||||
=== Configuration via properties file
|
||||
|
||||
The contents are identical to <<hibernate-gsg-tutorial-basic-config>> with one important difference...
|
||||
The `<mapping/>` element at the very end naming the annotated entity class using the `class` attribute.
|
||||
In this example, configuration properties are specified in a file named `hibernate.properties`.
|
||||
|
||||
.Configuration via `hibernate.properties`
|
||||
[source,properties]
|
||||
----
|
||||
# Database connection settings
|
||||
hibernate.connection.url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1
|
||||
hibernate.connection.username=sa
|
||||
hibernate.connection.password=
|
||||
|
||||
# Echo all executed SQL to console
|
||||
hibernate.show_sql=true
|
||||
hibernate.format_sql=true
|
||||
hibernate.highlight_sql=true
|
||||
|
||||
# Automatically export the schema
|
||||
hibernate.hbm2ddl.auto=create
|
||||
----
|
||||
|
||||
The following properties specify JDBC connection information:
|
||||
|
||||
.JDBC connection settings
|
||||
[%breakable,cols="35,~"]
|
||||
|===
|
||||
| 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
|
||||
|===
|
||||
|
||||
[NOTE]
|
||||
These tutorials use the H2 embedded database, so the values of these properties are specific to running H2 in its in-memory mode.
|
||||
|
||||
These properties enable logging of SQL to the console as it is executed, in an aesthetically pleasing format:
|
||||
|
||||
.Settings for SQL logging to the console
|
||||
[%breakable,cols="35,~"]
|
||||
|===
|
||||
| Configuration property name | Purpose
|
||||
|
||||
| `hibernate.show_sql` | If `true`, log SQL directly to the console
|
||||
| `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
|
||||
|===
|
||||
|
||||
When developing persistence logic with Hibernate, it's very important to be able to see exactly what SQL is being executed.
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-entity]]
|
||||
=== The annotated entity Java class
|
||||
|
||||
The entity class in this tutorial is `org.hibernate.tutorial.annotations.Event` which follows JavaBean conventions.
|
||||
In fact the class itself is identical to the one in <<hibernate-gsg-tutorial-basic-entity>>, except that annotations
|
||||
are used to provide the metadata, rather than a separate mapping file.
|
||||
The entity class in this tutorial is `org.hibernate.tutorial.annotations.Event`.
|
||||
Observe that:
|
||||
|
||||
- This class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields.
|
||||
This is recommended, but it's not a requirement.
|
||||
- The no-argument constructor, which is also a JavaBean convention, _is_ a requirement for all persistent classes.
|
||||
Hibernate needs to instantiate objects for you, using Java Reflection.
|
||||
The constructor should have package-private or `public` visibility, to allow Hibernate to generate proxies and optimized code for field access.
|
||||
|
||||
We use annotations to identify the class as an entity, and to map it to the relational schema.
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-entity-entity]]
|
||||
.Identifying the class as an entity
|
||||
====
|
||||
[source, JAVA]
|
||||
[source, java]
|
||||
----
|
||||
@Entity
|
||||
@Table( name = "EVENTS" )
|
||||
@Entity <1>
|
||||
@Table(name = "Events") <2>
|
||||
public class Event {
|
||||
...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `@jakarta.persistence.Entity` annotation is used to mark a class as an entity. It functions the same as the
|
||||
`<class/>` mapping element discussed in <<hibernate-gsg-tutorial-basic-mapping>>. Additionally the
|
||||
`@jakarta.persistence.Table` annotation explicitly specifies the table name. Without this specification, the default
|
||||
table name would be _EVENT_.
|
||||
<1> `@jakarta.persistence.Entity` marks the `Event` class as an entity.
|
||||
<2> `@jakarta.persistence.Table` explicitly specifies the name of the mapped table.
|
||||
Without this annotation, the table name would default to `Event`.
|
||||
|
||||
Every entity class must have an identifier.
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-entity-id]]
|
||||
.Identifying the identifier property
|
||||
====
|
||||
[source, JAVA]
|
||||
[source, java]
|
||||
----
|
||||
@Id
|
||||
@GeneratedValue(generator="increment")
|
||||
@GenericGenerator(name="increment", strategy = "increment")
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@Id <1>
|
||||
@GeneratedValue <2>
|
||||
private Long id;
|
||||
----
|
||||
====
|
||||
|
||||
`@jakarta.persistence.Id` marks the property which defines the entity's identifier.
|
||||
|
||||
`@jakarta.persistence.GeneratedValue` and `@org.hibernate.annotations.GenericGenerator` work in tandem
|
||||
to indicate that Hibernate should use Hibernate's `increment` generation strategy for this entity's identifier values.
|
||||
<1> `@jakarta.persistence.Id` marks the field as holding the identifier (primary key) of the entity.
|
||||
<2> `@jakarta.persistence.GeneratedValue` specifies that this is a _synthetic id_, that is, a system-generated identifier (a surrogate primary key).
|
||||
|
||||
Other fields of the entity are considered persistent by default.
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-entity-properties]]
|
||||
.Identifying basic properties
|
||||
====
|
||||
[source, JAVA]
|
||||
.Mapping basic properties
|
||||
[source, java]
|
||||
----
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
private String title;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "EVENT_DATE")
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
@Column(name = "eventDate") <1>
|
||||
private LocalDateTime date;
|
||||
----
|
||||
====
|
||||
|
||||
As in <<hibernate-gsg-tutorial-basic-mapping>>, the `date` property needs special handling to account for its special
|
||||
naming and its SQL type.
|
||||
|
||||
Attributes of an entity are considered persistent by default when mapping with annotations, which is why we don't see
|
||||
any mapping information associated with `title`.
|
||||
<1> `@jakarta.persistence.Column` explicitly specifies the name of a mapped column.
|
||||
Without this annotation, the column name would default to `date`, which is a keyword on some databases.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-test]]
|
||||
=== Example code
|
||||
|
||||
`org.hibernate.tutorial.annotations.AnnotationsIllustrationTest` is essentially the same as
|
||||
`org.hibernate.tutorial.hbm.NativeApiIllustrationTest` discussed in <<hibernate-gsg-tutorial-basic-test>>.
|
||||
The class `org.hibernate.tutorial.annotations.HibernateIllustrationTest` illustrates the use of the Hibernate's native APIs, including:
|
||||
|
||||
- `Session` and `SessionFactory`, and
|
||||
- `org.hibernate.boot` for configuration and bootstrap.
|
||||
|
||||
There are several different ways to configure and start Hibernate, and this is not even the most common approach.
|
||||
|
||||
[NOTE]
|
||||
The examples in these tutorials are presented as JUnit tests.
|
||||
A benefit of this approach is that `setUp()` and `tearDown()` roughly illustrate how a `org.hibernate.SessionFactory` is
|
||||
created when the program starts, and closed when the program terminates.
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-setUp]]
|
||||
.Obtaining the `SessionFactory`
|
||||
[source, java]
|
||||
----
|
||||
protected void setUp() {
|
||||
// A SessionFactory is set up once for an application!
|
||||
final StandardServiceRegistry registry =
|
||||
new StandardServiceRegistryBuilder()
|
||||
.build(); <1> <2>
|
||||
try {
|
||||
sessionFactory =
|
||||
new MetadataSources(registry) <3>
|
||||
.addAnnotatedClass(Event.class) <4>
|
||||
.buildMetadata() <5>
|
||||
.buildSessionFactory(); <6>
|
||||
}
|
||||
catch (Exception e) {
|
||||
// The registry would be destroyed by the SessionFactory, but we
|
||||
// had trouble building the SessionFactory so destroy it manually.
|
||||
StandardServiceRegistryBuilder.destroy(registry);
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> The `setUp()` method first builds a `StandardServiceRegistry` instance which incorporates configuration information into a working set of `Services` for use by the `SessionFactory`.
|
||||
<2> Here we put all configuration information in `hibernate.properties`, so there's not much interesting to see.
|
||||
<3> Using the `StandardServiceRegistry` we create the `MetadataSources` which lets us tell Hibernate about our domain model.
|
||||
<4> Here we have only one entity class to register.
|
||||
<5> An instance of `Metadata` represents a complete, partially-validated view of the application domain model.
|
||||
<6> The final step in the bootstrap process is to build a `SessionFactory` for the configured services and validated domain model.
|
||||
The `SessionFactory` is a thread-safe object that's instantiated once to serve the entire application.
|
||||
|
||||
The `SessionFactory` produces instances of `Session`.
|
||||
Each session should be thought of as representing a _unit of work_.
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-saving]]
|
||||
.Persisting entities
|
||||
[source, java]
|
||||
----
|
||||
sessionFactory.inTransaction(session -> { <1>
|
||||
session.persist(new Event("Our very first event!", now())); <2>
|
||||
session.persist(new Event("A follow up event", now()));
|
||||
});
|
||||
----
|
||||
<1> The `inTransaction()` method creates a session and starts a new transaction.
|
||||
<2> Here we create two new `Event` objects and hands them over to Hibernate, calling the `persist()` method to make these instances persistent.
|
||||
Hibernate is responsible for executing an `INSERT` statement for each `Event`.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-list]]
|
||||
.Obtaining a list of entities
|
||||
[source, java]
|
||||
----
|
||||
sessionFactory.inTransaction(session -> {
|
||||
session.createSelectionQuery("from Event", Event.class) <1>
|
||||
.getResultList() <2>
|
||||
.forEach(event -> out.println("Event (" + event.getDate() + ") : " + event.getTitle()));
|
||||
});
|
||||
----
|
||||
|
||||
<1> Here we use a very simple _Hibernate Query Language_ (HQL) statement to load all existing `Event` objects from the database.
|
||||
<2> Hibernate generates and executes the appropriate `SELECT` statement, and then instantiates and populates `Event` objects with the data in the query result set.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-further]]
|
||||
=== Take it further!
|
||||
|
||||
.Practice Exercises
|
||||
- [ ] Add an association to the `Event` entity to model a message thread. Use the
|
||||
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html[_User Guide_] for more details.
|
||||
- [ ] Add a callback to receive notifications when an `Event` is created, updated or deleted.
|
||||
Try the same with an event listener. Use the
|
||||
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html[_User Guide_] for more details.
|
||||
- [ ] Actually run this example to see the SQL executed by Hibernate displayed in the console.
|
||||
- [ ] Reconfigure the examples to connect to your own persistent relational database.
|
||||
- [ ] Add an association to the `Event` entity to model a message thread.
|
||||
See the _Introduction to Hibernate 6_ for details.
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
[[tutorial_envers]]
|
||||
== Tutorial Using Envers
|
||||
|
||||
NOTE: This tutorial is located within the download bundle under `envers/`.
|
||||
|
||||
.Objectives
|
||||
- [*] Annotate an entity as historical
|
||||
- [*] Configure Envers
|
||||
- [*] Use the Envers APIs to view and analyze historical data
|
||||
|
||||
****
|
||||
This tutorial is located within the download bundle under `envers/`.
|
||||
****
|
||||
|
||||
[[hibernate-gsg-tutorial-envers-config]]
|
||||
=== persistence.xml
|
||||
|
||||
This file was discussed in the Jakarta Persistence tutorial in <<hibernate-gsg-tutorial-jpa-config>>, and is essentially the same here.
|
||||
|
||||
This file is unchanged from <<hibernate-gsg-tutorial-jpa-config,what we had before>>.
|
||||
|
||||
[[hibernate-gsg-tutorial-envers-entity]]
|
||||
=== The annotated entity Java class
|
||||
|
||||
Again, the entity is largely the same as in <<hibernate-gsg-tutorial-jpa-entity>>. The major difference is the
|
||||
addition of the `@org.hibernate.envers.Audited` annotation, which tells Envers to automatically track changes to this
|
||||
entity.
|
||||
|
||||
The entity class is also almost identical to what we had <<hibernate-gsg-tutorial-annotations-entity,previously>>.
|
||||
The major difference is the addition of the annotation `@org.hibernate.envers.Audited`, which tells Envers to automatically track changes to this entity.
|
||||
|
||||
[[hibernate-gsg-tutorial-envers-test]]
|
||||
=== Example code
|
||||
|
@ -32,28 +30,23 @@ initial revision as well as the updated revision. A revision refers to a histor
|
|||
|
||||
[[hibernate-gsg-tutorial-envers-test-api]]
|
||||
.Using the `org.hibernate.envers.AuditReader`
|
||||
====
|
||||
[source, JAVA]
|
||||
[source, java]
|
||||
----
|
||||
public void testBasicUsage() {
|
||||
...
|
||||
AuditReader reader = AuditReaderFactory.get( entityManager );
|
||||
Event firstRevision = reader.find( Event.class, 2L, 1 );
|
||||
AuditReader reader = AuditReaderFactory.get( entityManager ); <1>
|
||||
Event firstRevision = reader.find( Event.class, 2L, 1 ); <2>
|
||||
...
|
||||
Event secondRevision = reader.find( Event.class, 2L, 2 );
|
||||
Event secondRevision = reader.find( Event.class, 2L, 2 ); <3>
|
||||
...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
We see that an `org.hibernate.envers.AuditReader` is obtained from the `org.hibernate.envers.AuditReaderFactory`
|
||||
which wraps the `jakarta.persistence.EntityManager`.
|
||||
|
||||
Next, the `find` method retrieves specific revisions of the entity. The first call says to find revision number
|
||||
1 of Event with id 2. The second call says to find revision number 2 of Event with id 2.
|
||||
<1> An `org.hibernate.envers.AuditReader` is obtained from the `org.hibernate.envers.AuditReaderFactory` which wraps the JPA `EntityManager`.
|
||||
<2> The `find` method retrieves specific revisions of the entity. The first call retrieves revision number 1 of the `Event` with id 2.
|
||||
<3> Later, the second call asks for revision number 2 of the `Event` with id 2.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-further]]
|
||||
[[hibernate-gsg-tutorial-envers-further]]
|
||||
=== Take it further!
|
||||
|
||||
.Practice Exercises
|
||||
|
|
|
@ -1,118 +1,124 @@
|
|||
[[tutorial_jpa]]
|
||||
== Tutorial Using the Java Persistence API (Jakarta Persistence)
|
||||
|
||||
NOTE: This tutorial is located within the download bundle under `entitymanager/`.
|
||||
== Tutorial using JPA-standard APIs
|
||||
|
||||
.Objectives
|
||||
- [*] Configure Hibernate using `peristence.xml`
|
||||
- [*] Bootstrap a Jakarta Persistence `EntityManagerFactory`
|
||||
- [*] Use annotations to provide mapping information
|
||||
- [*] Use Jakarta Persistence API calls
|
||||
- [*] Use `EntityManager` to persist and query data
|
||||
|
||||
|
||||
****
|
||||
This tutorial is located within the download bundle under `entitymanager/`.
|
||||
****
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-config]]
|
||||
=== persistence.xml
|
||||
|
||||
The previous tutorials used the Hibernate-specific `hibernate.cfg.xml` configuration file. Jakarta Persistence, however, defines
|
||||
a different bootstrap process that uses its own configuration file named `persistence.xml`. This bootstrapping process
|
||||
is defined by the Jakarta Persistence specification. In Java(TM) SE environments the persistence provider (Hibernate in this case)
|
||||
is required to locate all Jakarta Persistence configuration files by classpath lookup of the `META-INF/persistence.xml` resource name.
|
||||
|
||||
JPA defines a different bootstrap process, along with a standard configuration file format named `persistence.xml`.
|
||||
In Java(TM) SE environments the persistence provider (Hibernate) is required to locate every JPA configuration file in the classpath at the path `META-INF/persistence.xml`.
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-config-pu]]
|
||||
.persistence.xml
|
||||
====
|
||||
[source, XML]
|
||||
.Configuration via `persistence.xml`
|
||||
[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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
|
||||
version="2.0">
|
||||
<persistence-unit name="org.hibernate.tutorial.jpa">
|
||||
...
|
||||
|
||||
<persistence-unit name="org.hibernate.tutorial.jpa"> <1>
|
||||
<description>
|
||||
Persistence unit for the Jakarta Persistence tutorial of the Hibernate Getting Started Guide
|
||||
</description>
|
||||
|
||||
<class>org.hibernate.tutorial.em.Event</class> <2>
|
||||
|
||||
<properties> <3>
|
||||
<!-- Database connection settings -->
|
||||
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" />
|
||||
<property name="jakarta.persistence.jdbc.user" value="sa" />
|
||||
<property name="jakarta.persistence.jdbc.password" value="" />
|
||||
|
||||
<!-- Automatically export the schema -->
|
||||
<property name="jakarta.persistence.schema-generation.database.action" value="create" />
|
||||
|
||||
<!-- Echo all executed SQL to console -->
|
||||
<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>
|
||||
|
||||
----
|
||||
====
|
||||
<1> A `persistence.xml` file should provide a unique name for each _persistence unit_ it declares.
|
||||
Applications use this name to reference the configuration when obtaining an `EntityManagerFactory`.
|
||||
<2> The `<class/>` element registers our annotated entity class.
|
||||
<3> The settings specified as `<properties/>` elements were already discussed in <<hibernate-gsg-tutorial-annotations-config>>.
|
||||
Here JPA-standard property names are used where possible.
|
||||
|
||||
`persistence.xml` files should provide a unique name for each "persistence unit". Applications use this name to
|
||||
reference the configuration when obtaining an `jakarta.persistence.EntityManagerFactory` reference.
|
||||
|
||||
The settings defined in the `<properties/>` element are discussed in <<hibernate-gsg-tutorial-basic-config>>.
|
||||
Here the `jakarta.persistence`-prefixed varieties are used when possible. Notice that the remaining
|
||||
Hibernate-specific configuration setting names are now prefixed with `hibernate.`.
|
||||
|
||||
NOTE:: Configuration properties prefixed with the legacy Java EE "namespace" (`javax.persistence.*`) are also still
|
||||
supported, although the Jakarta EE version (`jakarta.persistence.*`) should be preferred
|
||||
|
||||
Additionally, the `<class/>` element functions the same as we saw in <<hibernate-gsg-tutorial-annotations-config>>.
|
||||
[NOTE]
|
||||
Configuration properties prefixed with the legacy Java EE namespace `javax.persistence` are still
|
||||
recognized, but the Jakarta EE namespace `jakarta.persistence` is now preferred.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-entity]]
|
||||
=== The annotated entity Java class
|
||||
|
||||
The entity is exactly the same as in <<hibernate-gsg-tutorial-annotations-entity>>.
|
||||
|
||||
The entity class is exactly the same as in <<hibernate-gsg-tutorial-annotations-entity>>.
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-test]]
|
||||
=== Example code
|
||||
|
||||
The previous tutorials used the Hibernate native APIs. This tutorial uses the Jakarta Persistence APIs.
|
||||
The previous tutorials used Hibernate native APIs.
|
||||
This tutorial uses the standard Jakarta Persistence APIs.
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-test-setUp]]
|
||||
.Obtaining the jakarta.persistence.EntityManagerFactory
|
||||
====
|
||||
[source, JAVA]
|
||||
[source, java]
|
||||
----
|
||||
protected void setUp() throws Exception {
|
||||
sessionFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
|
||||
protected void setUp() {
|
||||
sessionFactory = Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa"); <1>
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Notice again that the persistence unit name is `org.hibernate.tutorial.jpa`, which matches <<hibernate-gsg-tutorial-jpa-config-pu>>.
|
||||
<1> Notice again that the persistence unit name is `org.hibernate.tutorial.jpa`, which matches <<hibernate-gsg-tutorial-jpa-config-pu>>.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-test-saving]]
|
||||
.Saving (persisting) entities
|
||||
====
|
||||
[source, JAVA]
|
||||
The code to persist and query entities is almost identical to <<hibernate-gsg-tutorial-basic-test-saving>>.
|
||||
Unfortunately, `EntityManagerFactory` doesn't have a nice `inTransaction()` method like `SessionFactory` does, so we had to write our own:
|
||||
|
||||
.Managing transactions in JPA
|
||||
[source, java]
|
||||
----
|
||||
EntityManager entityManager = sessionFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
entityManager.persist( new Event( "Our very first event!", new Date() ) );
|
||||
entityManager.persist( new Event( "A follow up event", new Date() ) );
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
----
|
||||
====
|
||||
|
||||
The code is similar to <<hibernate-gsg-tutorial-basic-test-saving>>. The `jakarta.persistence.EntityManager` interface
|
||||
is used instead of the `org.hibernate.Session` interface. Jakarta Persistence calls this operation "persist" instead of "save".
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-jpa-test-list]]
|
||||
.Obtaining a list of entities
|
||||
====
|
||||
[source, JAVA]
|
||||
----
|
||||
entityManager = sessionFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList();
|
||||
for ( Event event : result ) {
|
||||
System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
|
||||
void inTransaction(Consumer<EntityManager> work) {
|
||||
EntityManager entityManager = entityManagerFactory.createEntityManager();
|
||||
EntityTransaction transaction = entityManager.getTransaction();
|
||||
try {
|
||||
transaction.begin();
|
||||
work.accept(entityManager);
|
||||
transaction.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (transaction.isActive()) {
|
||||
transaction.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
entityManager.close();
|
||||
}
|
||||
}
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
----
|
||||
====
|
||||
|
||||
Again, the code is pretty similar to what we saw in <<hibernate-gsg-tutorial-basic-test-list>>.
|
||||
[TIP]
|
||||
If you use JPA in Java SE, you'll need to copy/paste this function into your project.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-further]]
|
||||
[[hibernate-gsg-tutorial-jpa-further]]
|
||||
=== Take it further!
|
||||
|
||||
.Practice Exercises
|
||||
- [ ] Develop an EJB Session bean to investigate implications of using a container-managed
|
||||
persistence context. Try both stateless and stateful use-cases.
|
||||
- [ ] Use listeners with CDI-based injection to develop a JMS-based event message hub
|
||||
- [ ] Learn how to use CDI to inject a container-managed `EntityManager` in Quarkus.
|
||||
See https://quarkus.io/guides/hibernate-orm[the Quarkus website] for instructions.
|
|
@ -1,231 +0,0 @@
|
|||
[[tutorial-native]]
|
||||
== Tutorial Using Native Hibernate APIs and hbm.xml Mapping
|
||||
|
||||
NOTE: This tutorial is located within the download bundle under `basic/`.
|
||||
|
||||
.Objectives
|
||||
- [*] Bootstrap a Hibernate `SessionFactory`
|
||||
- [*] Use Hibernate mapping (`hbm.xml`) files to provide mapping information
|
||||
- [*] Use the Hibernate native APIs
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-config]]
|
||||
=== The Hibernate configuration file
|
||||
|
||||
For this tutorial, the `hibernate.cfg.xml` file defines the Hibernate configuration information.
|
||||
|
||||
The `connection.driver_class`, `connection.url`, `connection.username` and `connection.password` `<property/>` elements
|
||||
define JDBC connection information. These tutorials utilize the H2 in-memory database, so the values of these properties
|
||||
are all specific to running H2 in its in-memory mode. `connection.pool_size` is used to configure the number of
|
||||
connections in Hibernate's built-in connection pool.
|
||||
|
||||
IMPORTANT: The built-in Hibernate connection pool is in no way intended for production use. It lacks several
|
||||
features found on production-ready connection pools.
|
||||
|
||||
The `dialect` property specifies the particular SQL variant with which Hibernate will converse.
|
||||
|
||||
TIP: In most cases, Hibernate is able to properly determine which dialect to use. This is particularly useful
|
||||
if your application targets multiple databases.
|
||||
|
||||
The `hbm2ddl.auto` property enables automatic generation of database schemas directly into the database.
|
||||
|
||||
Finally, add the mapping file(s) for persistent classes to the configuration. The `resource` attribute of the
|
||||
`<mapping/>` element causes Hibernate to attempt to locate that mapping as a classpath resource using a
|
||||
`java.lang.ClassLoader` lookup.
|
||||
|
||||
There are many ways and options to bootstrap a Hibernate `SessionFactory`. For additional details, see
|
||||
the _Native Bootstrapping_ topical guide.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-entity]]
|
||||
=== The entity Java class
|
||||
|
||||
The entity class for this tutorial is `org.hibernate.tutorial.hbm.Event`
|
||||
|
||||
.Notes About the Entity
|
||||
* This class uses standard JavaBean naming conventions for property getter and setter methods, as well as
|
||||
private visibility for the fields. Although this is the recommended design, it is not required.
|
||||
* The no-argument constructor, which is also a JavaBean convention, is a requirement for all persistent classes.
|
||||
Hibernate needs to create objects for you, using Java Reflection. The constructor can be private. However, package
|
||||
or public visibility is required for runtime proxy generation and efficient data retrieval without bytecode
|
||||
instrumentation.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-mapping]]
|
||||
=== The mapping file
|
||||
|
||||
The mapping file for this tutorial is the classpath resource `org/hibernate/tutorial/hbm/Event.hbm.xml` (as discussed above).
|
||||
|
||||
Hibernate uses the mapping metadata to determine how to load and store objects of the persistent class. The Hibernate
|
||||
mapping file is one choice for providing Hibernate with this metadata.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-mapping-class]]
|
||||
.The class mapping element
|
||||
====
|
||||
[source, XML]
|
||||
----
|
||||
<class name="Event" table="EVENTS">
|
||||
...
|
||||
</class>
|
||||
----
|
||||
====
|
||||
|
||||
.Functions of the <varname>class</varname> mapping element
|
||||
* The `name` attribute (combined here with the `package` attribute from the containing `<hibernate-mapping/>` element)
|
||||
names the FQN of the class to be defined as an entity.
|
||||
* The `table` attribute names the database table which contains the data for this entity.
|
||||
|
||||
Instances of the `Event` class are now mapped to rows in the `EVENTS` database table.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-mapping-id]]
|
||||
.The id mapping element
|
||||
====
|
||||
[source, XML]
|
||||
----
|
||||
<id name="id" column="EVENT_ID">
|
||||
...
|
||||
</id>
|
||||
----
|
||||
====
|
||||
|
||||
Hibernate uses the property named by the `<id/>` element to uniquely identify rows in the table.
|
||||
|
||||
IMPORTANT: It is not required for the id element to map to the table's actual primary key column(s), but it is
|
||||
the normal convention. Tables mapped in Hibernate do not even need to define primary keys. However, it is strongly
|
||||
recommend that all schemas define proper referential integrity. Therefore id and primary key are used interchangeably
|
||||
throughout Hibernate documentation.
|
||||
|
||||
The `<id/>` element here names the EVENT_ID column as the primary key of the EVENTS table. It also identifies the
|
||||
`id` property of the `Event` class as the property containing the identifier value.
|
||||
|
||||
The `generator` element informs Hibernate about which strategy is used to generated primary key values for this entity.
|
||||
This example uses a simple incrementing count.
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-mapping-property]]
|
||||
.The property mapping element
|
||||
====
|
||||
[source, XML]
|
||||
----
|
||||
<property name="date" type="timestamp" column="EVENT_DATE"/>
|
||||
<property name="title"/>
|
||||
----
|
||||
====
|
||||
|
||||
The two `<property/>` elements declare the remaining two persistent properties of the `Event` class: `date` and `title`.
|
||||
The `date` property mapping includes the `column` attribute, but the `title` does not.
|
||||
In the absence of a `column` attribute, Hibernate uses the property name as the column name.
|
||||
This is appropriate for `title`, but since `date` is a reserved keyword in most databases, you need to specify a
|
||||
non-reserved word for the column name.
|
||||
|
||||
The `title` mapping also lacks a type attribute. The types declared and used in the mapping files are neither Java data
|
||||
types nor SQL database types. Instead, they are *Hibernate mapping types*, which are converters which translate between
|
||||
Java and SQL data types. Hibernate attempts to determine the correct conversion and mapping type autonomously if the
|
||||
type attribute is not specified in the mapping, by using Java reflection to determine the Java type of the declared
|
||||
property and using a default mapping type for that Java type.
|
||||
|
||||
In some cases this automatic detection might not choose the default you expect or need, as seen with the
|
||||
`date` property. Hibernate cannot know if the property, which is of type `java.util.Date`, should map to an SQL
|
||||
_DATE_, _TIME_, or _TIMESTAMP_ datatype. Full date and time information is preserved by mapping the property to
|
||||
the _timestamp_ converter, which identifies the converter as declared by `org.hibernate.type.StandardBasicTypes.TIMESTAMP`.
|
||||
|
||||
TIP: Hibernate determines the mapping type using reflection when the mapping files are processed. This process adds
|
||||
overhead in terms of time and resources. If startup performance is important, consider explicitly defining the type
|
||||
to use.
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test]]
|
||||
=== Example code
|
||||
|
||||
The `org.hibernate.tutorial.hbm.NativeApiIllustrationTest` class illustrates using the Hibernate native API.
|
||||
|
||||
NOTE: The examples in these tutorials are presented as JUnit tests, for ease of use. One benefit of this
|
||||
approach is that `setUp` and `tearDown` roughly illustrate how a `org.hibernate.SessionFactory` is created at the
|
||||
start-up of an application and closed at the end of the application lifecycle.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-setUp]]
|
||||
.Obtaining the `org.hibernate.SessionFactory`
|
||||
====
|
||||
[source, JAVA]
|
||||
----
|
||||
protected void setUp() throws Exception {
|
||||
// A SessionFactory is set up once for an application!
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.configure() // configures settings from hibernate.cfg.xml
|
||||
.build();
|
||||
try {
|
||||
sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
|
||||
// so destroy it manually.
|
||||
StandardServiceRegistryBuilder.destroy( registry );
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The `setUp` method first builds a `org.hibernate.boot.registry.StandardServiceRegistry` instance which incorporates
|
||||
configuration information into a working set of Services for use by the SessionFactory. In this tutorial
|
||||
we defined all configuration information in `hibernate.cfg.xml` so there is not much interesting to see here.
|
||||
|
||||
Using the `StandardServiceRegistry` we create the `org.hibernate.boot.MetadataSources` which is the start point for
|
||||
telling Hibernate about your domain model. Again, since we defined that in `hibernate.cfg.xml` so there is not much
|
||||
interesting to see here.
|
||||
|
||||
`org.hibernate.boot.Metadata` represents the complete, partially validated view of the application domain model which the
|
||||
`SessionFactory` will be based on.
|
||||
|
||||
The final step in the bootstrap process is to build the `SessionFactory`. The `SessionFactory` is a
|
||||
thread-safe object that is instantiated once to serve the entire application.
|
||||
|
||||
The `SessionFactory` acts as a factory for `org.hibernate.Session` instances, which should be thought of
|
||||
as a corollary to a "unit of work".
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-saving]]
|
||||
.Saving entities
|
||||
====
|
||||
[source, JAVA]
|
||||
----
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save( new Event( "Our very first event!", new Date() ) );
|
||||
session.save( new Event( "A follow up event", new Date() ) );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
----
|
||||
====
|
||||
|
||||
`testBasicUsage()` first creates some new `Event` objects and hands them over to Hibernate for management, using the
|
||||
`save()` method. Hibernate now takes responsibility to perform an _INSERT_ on the database for each `Event`.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-basic-test-list]]
|
||||
.Obtaining a list of entities
|
||||
====
|
||||
[source, JAVA]
|
||||
----
|
||||
session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
List result = session.createQuery( "from Event" ).list();
|
||||
for ( Event event : (List<Event>) result ) {
|
||||
System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
----
|
||||
====
|
||||
|
||||
Here we see an example of the Hibernate Query Language (HQL) to load all existing `Event` objects from the database
|
||||
by generating the appropriate _SELECT_ SQL, sending it to the database and populating `Event` objects with the result
|
||||
set data.
|
||||
|
||||
|
||||
[[hibernate-gsg-tutorial-annotations-further]]
|
||||
=== Take it further!
|
||||
|
||||
.Practice Exercises
|
||||
- [ ] Reconfigure the examples to connect to your own persistent relational database.
|
||||
- [ ] Add an association to the `Event` entity to model a message thread.
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.tutorial.annotations;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Illustrates the use of Hibernate native APIs. The code here is unchanged from the {@code basic} example, the
|
||||
* only difference being the use of annotations to supply the metadata instead of Hibernate mapping files.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AnnotationsIllustrationTest extends TestCase {
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
// A SessionFactory is set up once for an application!
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.configure() // configures settings from hibernate.cfg.xml
|
||||
.build();
|
||||
try {
|
||||
sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
|
||||
// so destroy it manually.
|
||||
StandardServiceRegistryBuilder.destroy( registry );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if ( sessionFactory != null ) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testBasicUsage() {
|
||||
// create a couple of events...
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save( new Event( "Our very first event!", new Date() ) );
|
||||
session.save( new Event( "A follow up event", new Date() ) );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// now lets pull events from the database and list them
|
||||
session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
List result = session.createQuery( "from Event" ).list();
|
||||
for ( Event event : (List<Event>) result ) {
|
||||
System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
|
@ -23,38 +23,36 @@
|
|||
*/
|
||||
package org.hibernate.tutorial.annotations;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
@Entity
|
||||
@Table( name = "EVENTS" )
|
||||
@Table(name = "Events")
|
||||
public class Event {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
private Date date;
|
||||
|
||||
@Column(name = "eventDate")
|
||||
private LocalDateTime date;
|
||||
|
||||
public Event() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Event(String title, Date date) {
|
||||
public Event(String title, LocalDateTime date) {
|
||||
// for application use, to create new events
|
||||
this.title = title;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator="increment")
|
||||
@GenericGenerator(name="increment", strategy = "increment")
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -63,13 +61,11 @@ public class Event {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "EVENT_DATE")
|
||||
public Date getDate() {
|
||||
public LocalDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
public void setDate(LocalDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,9 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.tutorial.hbm;
|
||||
package org.hibernate.tutorial.annotations;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
@ -34,55 +33,57 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import static java.lang.System.out;
|
||||
import static java.time.LocalDateTime.now;
|
||||
|
||||
/**
|
||||
* Illustrates use of Hibernate native APIs.
|
||||
* Illustrates the use of Hibernate native APIs, including the use
|
||||
* of org.hibernate.boot for configuration and bootstrap.
|
||||
* Configuration properties are sourced from hibernate.properties.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NativeApiIllustrationTest extends TestCase {
|
||||
public class HibernateIllustrationTest extends TestCase {
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
protected void setUp() {
|
||||
// A SessionFactory is set up once for an application!
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.configure() // configures settings from hibernate.cfg.xml
|
||||
final StandardServiceRegistry registry =
|
||||
new StandardServiceRegistryBuilder()
|
||||
.build();
|
||||
try {
|
||||
sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
|
||||
sessionFactory =
|
||||
new MetadataSources(registry)
|
||||
.addAnnotatedClass(Event.class)
|
||||
.buildMetadata()
|
||||
.buildSessionFactory();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
|
||||
// so destroy it manually.
|
||||
StandardServiceRegistryBuilder.destroy( registry );
|
||||
// The registry would be destroyed by the SessionFactory, but we
|
||||
// had trouble building the SessionFactory so destroy it manually.
|
||||
StandardServiceRegistryBuilder.destroy(registry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
protected void tearDown() {
|
||||
if ( sessionFactory != null ) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testBasicUsage() {
|
||||
// create a couple of events...
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save( new Event( "Our very first event!", new Date() ) );
|
||||
session.save( new Event( "A follow up event", new Date() ) );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
sessionFactory.inTransaction(session -> {
|
||||
session.persist(new Event("Our very first event!", now()));
|
||||
session.persist(new Event("A follow up event", now()));
|
||||
});
|
||||
|
||||
// now lets pull events from the database and list them
|
||||
session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
List result = session.createQuery( "from Event" ).list();
|
||||
for ( Event event : (List<Event>) result ) {
|
||||
System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
|
||||
}
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
sessionFactory.inTransaction(session -> {
|
||||
session.createSelectionQuery("from Event", Event.class).getResultList()
|
||||
.forEach(event -> out.println("Event (" + event.getDate() + ") : " + event.getTitle()));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-configuration PUBLIC
|
||||
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||
|
||||
<hibernate-configuration>
|
||||
|
||||
<session-factory>
|
||||
|
||||
<!-- Database connection settings -->
|
||||
<property name="connection.driver_class">org.h2.Driver</property>
|
||||
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1</property>
|
||||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"></property>
|
||||
|
||||
<!-- JDBC connection pool (use the built-in) -->
|
||||
<property name="connection.pool_size">1</property>
|
||||
|
||||
<!-- SQL dialect -->
|
||||
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||
|
||||
<!-- Disable the second-level cache -->
|
||||
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
|
||||
|
||||
<!-- Echo all executed SQL to stdout -->
|
||||
<property name="show_sql">true</property>
|
||||
|
||||
<!-- Drop and re-create the database schema on startup -->
|
||||
<property name="hbm2ddl.auto">create</property>
|
||||
|
||||
<!-- Names the annotated entity class -->
|
||||
<mapping class="org.hibernate.tutorial.annotations.Event"/>
|
||||
|
||||
</session-factory>
|
||||
|
||||
</hibernate-configuration>
|
|
@ -0,0 +1,12 @@
|
|||
# Database connection settings
|
||||
hibernate.connection.url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1
|
||||
hibernate.connection.username=sa
|
||||
hibernate.connection.password=
|
||||
|
||||
# Echo all executed SQL to console
|
||||
hibernate.show_sql=true
|
||||
hibernate.format_sql=true
|
||||
hibernate.highlight_sql=true
|
||||
|
||||
# Automatically export the schema
|
||||
hibernate.hbm2ddl.auto=create
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.hibernate.tutorials</groupId>
|
||||
<artifactId>hibernate-tutorials</artifactId>
|
||||
<version>$version</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hibernate-tutorial-hbm</artifactId>
|
||||
<name>Hibernate hbm.xml Tutorial</name>
|
||||
<description>Hibernate tutorial illustrating the use of native APIs and hbm.xml for mapping metadata</description>
|
||||
|
||||
<properties>
|
||||
<!-- Skip artifact deployment -->
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.tutorial.hbm">
|
||||
|
||||
<class name="Event" table="EVENTS">
|
||||
<id name="id" column="EVENT_ID">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="date" type="timestamp" column="EVENT_DATE"/>
|
||||
<property name="title"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.tutorial.hbm;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Event {
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
private Date date;
|
||||
|
||||
public Event() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Event(String title, Date date) {
|
||||
// for application use, to create new events
|
||||
this.title = title;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-configuration PUBLIC
|
||||
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||
|
||||
<hibernate-configuration>
|
||||
|
||||
<session-factory>
|
||||
|
||||
<!-- Database connection settings -->
|
||||
<property name="connection.driver_class">org.h2.Driver</property>
|
||||
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1</property>
|
||||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"/>
|
||||
|
||||
<!-- JDBC connection pool (use the built-in) -->
|
||||
<property name="connection.pool_size">1</property>
|
||||
|
||||
<!-- SQL dialect -->
|
||||
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||
|
||||
<!-- Disable the second-level cache -->
|
||||
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
|
||||
|
||||
<!-- Echo all executed SQL to stdout -->
|
||||
<property name="show_sql">true</property>
|
||||
|
||||
<!-- Drop and re-create the database schema on startup -->
|
||||
<property name="hbm2ddl.auto">create</property>
|
||||
|
||||
<mapping resource="org/hibernate/tutorial/hbm/Event.hbm.xml"/>
|
||||
|
||||
</session-factory>
|
||||
|
||||
</hibernate-configuration>
|
|
@ -23,38 +23,36 @@
|
|||
*/
|
||||
package org.hibernate.tutorial.em;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
@Entity
|
||||
@Table( name = "EVENTS" )
|
||||
@Table(name = "Events")
|
||||
public class Event {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
private Date date;
|
||||
|
||||
@Column(name = "eventDate")
|
||||
private LocalDateTime date;
|
||||
|
||||
public Event() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Event(String title, Date date) {
|
||||
public Event(String title, LocalDateTime date) {
|
||||
// for application use, to create new events
|
||||
this.title = title;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator="increment")
|
||||
@GenericGenerator(name="increment", strategy = "increment")
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -63,13 +61,11 @@ public class Event {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "EVENT_DATE")
|
||||
public Date getDate() {
|
||||
public LocalDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
public void setDate(LocalDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,51 +23,73 @@
|
|||
*/
|
||||
package org.hibernate.tutorial.em;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.Persistence;
|
||||
import jakarta.persistence.EntityTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import static java.lang.System.out;
|
||||
import static java.time.LocalDateTime.now;
|
||||
|
||||
import static jakarta.persistence.Persistence.createEntityManagerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Illustrates basic use of Hibernate as a Jakarta Persistence provider.
|
||||
* Configuration properties are sourced from persistence.xml.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityManagerIllustrationTest extends TestCase {
|
||||
public class JPAIllustrationTest extends TestCase {
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
// like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
|
||||
// IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
|
||||
entityManagerFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
|
||||
protected void setUp() {
|
||||
// an EntityManagerFactory is set up once for an application
|
||||
// IMPORTANT: notice how the name here matches the name we
|
||||
// gave the persistence-unit in persistence.xml
|
||||
entityManagerFactory = createEntityManagerFactory("org.hibernate.tutorial.jpa");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
protected void tearDown() {
|
||||
entityManagerFactory.close();
|
||||
}
|
||||
|
||||
public void testBasicUsage() {
|
||||
// create a couple of events...
|
||||
EntityManager entityManager = entityManagerFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
entityManager.persist( new Event( "Our very first event!", new Date() ) );
|
||||
entityManager.persist( new Event( "A follow up event", new Date() ) );
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
inTransaction(entityManager -> {
|
||||
entityManager.persist(new Event("Our very first event!", now()));
|
||||
entityManager.persist(new Event("A follow up event", now()));
|
||||
});
|
||||
|
||||
// now lets pull events from the database and list them
|
||||
entityManager = entityManagerFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList();
|
||||
for ( Event event : result ) {
|
||||
System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
|
||||
inTransaction(entityManager -> {
|
||||
entityManager.createQuery("select e from Event e", Event.class).getResultList()
|
||||
.forEach(event -> out.println("Event (" + event.getDate() + ") : " + event.getTitle()));
|
||||
});
|
||||
}
|
||||
entityManager.getTransaction().commit();
|
||||
|
||||
void inTransaction(Consumer<EntityManager> work) {
|
||||
EntityManager entityManager = entityManagerFactory.createEntityManager();
|
||||
EntityTransaction transaction = entityManager.getTransaction();
|
||||
try {
|
||||
transaction.begin();
|
||||
work.accept(entityManager);
|
||||
transaction.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (transaction.isActive()) {
|
||||
transaction.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
entityManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,13 +17,18 @@
|
|||
<class>org.hibernate.tutorial.em.Event</class>
|
||||
|
||||
<properties>
|
||||
<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver" />
|
||||
<!-- Database connection settings -->
|
||||
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" />
|
||||
<property name="jakarta.persistence.jdbc.user" value="sa" />
|
||||
<property name="jakarta.persistence.jdbc.password" value="" />
|
||||
|
||||
<!-- Automatically export the schema -->
|
||||
<property name="jakarta.persistence.schema-generation.database.action" value="create" />
|
||||
|
||||
<!-- Echo all executed SQL to console -->
|
||||
<property name="hibernate.show_sql" value="true" />
|
||||
<property name="hibernate.hbm2ddl.auto" value="create" />
|
||||
<property name="hibernate.format_sql" value="true" />
|
||||
<property name="hibernate.highlight_sql" value="true" />
|
||||
</properties>
|
||||
|
||||
</persistence-unit>
|
||||
|
|
|
@ -27,18 +27,22 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.Persistence;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.hibernate.envers.AuditReader;
|
||||
import org.hibernate.envers.AuditReaderFactory;
|
||||
|
||||
import static java.time.LocalDateTime.now;
|
||||
|
||||
import static jakarta.persistence.Persistence.createEntityManagerFactory;
|
||||
|
||||
/**
|
||||
* Illustrates the set up and use of Envers.
|
||||
* Illustrates the setup and use of Envers.
|
||||
* <p>
|
||||
* This example is different from the others in that we really need to save multiple revisions to the entity in
|
||||
* order to get a good look at Envers in action.
|
||||
* This example is different from the others because we need to have
|
||||
* multiple revisions to the entity in order to get a good look at
|
||||
* Envers in action.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -46,14 +50,12 @@ public class EnversIllustrationTest extends TestCase {
|
|||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
// like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
|
||||
// IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
|
||||
entityManagerFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.envers" );
|
||||
protected void setUp() {
|
||||
entityManagerFactory = createEntityManagerFactory( "org.hibernate.tutorial.envers" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
protected void tearDown() {
|
||||
entityManagerFactory.close();
|
||||
}
|
||||
|
||||
|
@ -61,8 +63,8 @@ public class EnversIllustrationTest extends TestCase {
|
|||
// create a couple of events
|
||||
EntityManager entityManager = entityManagerFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
entityManager.persist( new Event( "Our very first event!", new Date() ) );
|
||||
entityManager.persist( new Event( "A follow up event", new Date() ) );
|
||||
entityManager.persist( new Event( "Our very first event!", now() ) );
|
||||
entityManager.persist( new Event( "A follow up event", now() ) );
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
|
||||
|
@ -82,7 +84,7 @@ public class EnversIllustrationTest extends TestCase {
|
|||
entityManager = entityManagerFactory.createEntityManager();
|
||||
entityManager.getTransaction().begin();
|
||||
Event myEvent = entityManager.find( Event.class, 2L ); // we are using the increment generator, so we know 2 is a valid id
|
||||
myEvent.setDate( new Date() );
|
||||
myEvent.setDate( now() );
|
||||
myEvent.setTitle( myEvent.getTitle() + " (rescheduled)" );
|
||||
entityManager.getTransaction().commit();
|
||||
entityManager.close();
|
||||
|
|
|
@ -23,40 +23,39 @@
|
|||
*/
|
||||
package org.hibernate.tutorial.envers;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
@Entity
|
||||
@Table( name = "EVENTS" )
|
||||
@Audited // <--- this tell Envers to audit (track changes to) this entity
|
||||
@Table(name = "Events")
|
||||
@Audited // <--- this tells Envers to audit (track changes to) this entity
|
||||
public class Event {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
private Date date;
|
||||
|
||||
@Column(name = "eventDate")
|
||||
private LocalDateTime date;
|
||||
|
||||
public Event() {
|
||||
// this form used by Hibernate
|
||||
}
|
||||
|
||||
public Event(String title, Date date) {
|
||||
public Event(String title, LocalDateTime date) {
|
||||
// for application use, to create new events
|
||||
this.title = title;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator="increment")
|
||||
@GenericGenerator(name="increment", strategy = "increment")
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -65,13 +64,11 @@ public class Event {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "EVENT_DATE")
|
||||
public Date getDate() {
|
||||
public LocalDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
public void setDate(LocalDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
|
@ -82,11 +79,4 @@ public class Event {
|
|||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = title.hashCode();
|
||||
result = 31 * result + date.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,18 @@
|
|||
<class>org.hibernate.tutorial.envers.Event</class>
|
||||
|
||||
<properties>
|
||||
<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver" />
|
||||
<!-- Database connection settings -->
|
||||
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" />
|
||||
<property name="jakarta.persistence.jdbc.user" value="sa" />
|
||||
<property name="jakarta.persistence.jdbc.password" value="" />
|
||||
|
||||
<!-- Automatically export the schema -->
|
||||
<property name="jakarta.persistence.schema-generation.database.action" value="create" />
|
||||
|
||||
<!-- Echo all executed SQL to console -->
|
||||
<property name="hibernate.show_sql" value="true" />
|
||||
<property name="hibernate.hbm2ddl.auto" value="create" />
|
||||
<property name="hibernate.format_sql" value="true" />
|
||||
<property name="hibernate.highlight_sql" value="true" />
|
||||
</properties>
|
||||
|
||||
</persistence-unit>
|
||||
|
|
|
@ -349,8 +349,8 @@ span.icon>.fa{cursor:default}
|
|||
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
|
||||
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
|
||||
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
|
||||
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||
.conum[data-value] *{color:#fff!important}
|
||||
.conum[data-value]{display:inline-block;color:black!important;background-color:white;-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||
.conum[data-value] *{color:black!important}
|
||||
.conum[data-value]+b{display:none}
|
||||
.conum[data-value]:after{content:attr(data-value)}
|
||||
pre .conum[data-value]{position:relative;top:-.125em}
|
||||
|
|
|
@ -52,11 +52,6 @@ import static java.util.Comparator.comparingInt;
|
|||
*/
|
||||
public class QueryEngineImpl implements QueryEngine {
|
||||
|
||||
/**
|
||||
* The default soft reference count.
|
||||
*/
|
||||
public static final int DEFAULT_QUERY_PLAN_MAX_COUNT = 2048;
|
||||
|
||||
private static final Logger LOG_HQL_FUNCTIONS = CoreLogging.logger("org.hibernate.HQL_FUNCTIONS");
|
||||
|
||||
public static QueryEngine from(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata) {
|
||||
|
@ -205,7 +200,7 @@ public class QueryEngineImpl implements QueryEngine {
|
|||
if ( explicitUseCache || explicitMaxPlanSize != null && explicitMaxPlanSize > 0 ) {
|
||||
final int size = explicitMaxPlanSize != null
|
||||
? explicitMaxPlanSize
|
||||
: DEFAULT_QUERY_PLAN_MAX_COUNT;
|
||||
: QueryEngine.DEFAULT_QUERY_PLAN_MAX_COUNT;
|
||||
|
||||
return new QueryInterpretationCacheStandardImpl( size, statisticsSupplier );
|
||||
}
|
||||
|
|
|
@ -25,6 +25,11 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
@Incubating
|
||||
public interface QueryEngine {
|
||||
|
||||
/**
|
||||
* The default soft reference count.
|
||||
*/
|
||||
int DEFAULT_QUERY_PLAN_MAX_COUNT = 2048;
|
||||
|
||||
NativeQueryInterpreter getNativeQueryInterpreter();
|
||||
|
||||
QueryInterpretationCache getInterpretationCache();
|
||||
|
|
Loading…
Reference in New Issue