Hibernate is anObject/Relational Mapping (ORM) solution for programs written in Java and other JVMlanguages.
While a strong background in SQL is not required to use Hibernate, a basic understanding of its concepts is useful - especially the principles ofdata modeling.Understanding the basics of transactions and design patterns such asUnit of Work are important as well.
Hibernate is broken into a number of modules/artifacts under theorg.hibernate.ormgroup. The main artifact is namedhibernate-core.
This guide uses 7.2.0.CR3 as the Hibernate version for illustration purposes. Be sure to changethis version, if necessary, to the version you wish to use. |
We can declare a dependency on this artifact usingGradle
dependencies{implementation"org.hibernate.orm:hibernate-core:7.2.0.CR3"}orMaven:
<dependency><groupId>org.hibernate.orm</groupId><artifactId>hibernate-core</artifactId><version>7.2.0.CR3</version></dependency>As mentioned earlier, Hibernate ORM is broken into a number of modules with the intent of isolatingtransitive dependencies based on the features being used or not.
| The core object/relational mapping engine |
| Entity versioning and auditing |
| Support for spatial/GIS data types usingGeoLatte |
| An annotation processor that generates a JPA-compliant metamodel, plus optional Hibernate extras |
| Support for mathematical vector types and functions useful for AI/ML topics like vector similarity search and Retrieval-Augmented Generation (RAG) |
| Support forAgroal connection pooling |
| Support forC3P0 connection pooling |
| Support forHikariCP connection pooling |
| Integration withJCache, allowing any compliant implementation as a second-level cache provider |
| Experimental extension to make it easier to compile applications as aGraalVM native image |
| Integration withMicrometer metrics |
| Additionalcommunity-supported SQL dialects |
| A series of JUnit extensions for testing Hibernate ORM functionality |
| |||
| |||
| |||
Hibernate also provides a platform (BOM in Maven terminology) module which can be used to align versions of the Hibernate modules along with the versions of its libraries. The platform artifact is namedhibernate-platform.
To apply the platform in Gradle
dependencies{implementationplatform"org.hibernate.orm:hibernate-platform:7.2.0.CR3"// use the versions from the platformimplementation"org.hibernate.orm:hibernate-core"implementation"jakarta.transaction:jakarta.transaction-api"}See theGradle documentation for capabilities of applying a platform.
To apply the platform (BOM) in Maven
<dependency><groupId>org.hibernate.orm</groupId><artifactId>hibernate-core</artifactId></dependency><dependency><groupId>jakarta.transaction</groupId><artifactId>jakarta.transaction-api</artifactId></dependency><dependencyManagement><dependencies><dependency><groupId>org.hibernate.orm</groupId><artifactId>hibernate-platform</artifactId><version>7.2.0.CR3</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement> Configure Hibernate usinghibernate.properties
Create aSessionFactory usingnative bootstrapping
Use annotations to provide mapping information
UseSession to persist and query data
This tutorial is located within the download bundle underannotations/.
In this example, configuration properties are specified in a file namedhibernate.properties.
hibernate.properties# Database connection settingshibernate.connection.url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1hibernate.connection.username=sahibernate.connection.password=# Echo all executed SQL to consolehibernate.show_sql=truehibernate.format_sql=truehibernate.highlight_sql=true# Automatically export the schemahibernate.hbm2ddl.auto=createThe following properties specify JDBC connection information:
| Configuration property name | Purpose |
|---|---|
| JDBC URL of your database |
| Your database credentials |
| 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:
| Configuration property name | Purpose |
|---|---|
| If |
| If |
| If |
When developing persistence logic with Hibernate, it’s very important to be able to see exactly what SQL is being executed.
The entity class in this tutorial isorg.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 orpublic visibility, to allow Hibernate to generate proxies and optimized code for field access.
| TheEntity types section of the User Guide covers the complete set of requirements for the entity class. |
We use annotations to identify the class as an entity, and to map it to the relational schema.
@Entity(1)@Table(name="Events")(2)publicclassEvent{...}| 1 | @jakarta.persistence.Entity marks theEvent class as an entity. |
| 2 | @jakarta.persistence.Table explicitly specifies the name of the mapped table.Without this annotation, the table name would default toEvent. |
Every entity class must have an identifier.
@Id(1)@GeneratedValue(2)privateLongid;| 1 | @jakarta.persistence.Id marks the field as holding the identifier (primary key) of the entity. |
| 2 | @jakarta.persistence.GeneratedValue specifies that this is asynthetic id, that is, a system-generated identifier (a surrogate primary key). |
Other fields of the entity are considered persistent by default.
privateStringtitle;@Column(name="eventDate")(1)privateLocalDateTimedate;| 1 | @jakarta.persistence.Column explicitly specifies the name of a mapped column.Without this annotation, the column name would default todate, which is a keyword on some databases. |
The classorg.hibernate.tutorial.annotations.HibernateIllustrationTest illustrates the use of the Hibernate’s native APIs, including:
Session andSessionFactory, 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.
The examples in these tutorials are presented as JUnit tests.A benefit of this approach is thatsetUp() andtearDown() roughly illustrate how aorg.hibernate.SessionFactory iscreated when the program starts, and closed when the program terminates. |
SessionFactoryprotectedvoidsetUp(){// A SessionFactory is set up once for an application!finalStandardServiceRegistryregistry=newStandardServiceRegistryBuilder().build();(1)(2)try{sessionFactory=newMetadataSources(registry)(3).addAnnotatedClass(Event.class)(4).buildMetadata()(5).buildSessionFactory();(6)}catch(Exceptione){// The registry would be destroyed by the SessionFactory, but we// had trouble building the SessionFactory so destroy it manually.StandardServiceRegistryBuilder.destroy(registry);}}| 1 | ThesetUp() method first builds aStandardServiceRegistry instance which incorporates configuration information into a working set ofServices for use by theSessionFactory. |
| 2 | Here we put all configuration information inhibernate.properties, so there’s not much interesting to see. |
| 3 | Using theStandardServiceRegistry we create theMetadataSources which lets us tell Hibernate about our domain model. |
| 4 | Here we have only one entity class to register. |
| 5 | An instance ofMetadata represents a complete, partially-validated view of the application domain model. |
| 6 | The final step in the bootstrap process is to build aSessionFactory for the configured services and validated domain model.TheSessionFactory is a thread-safe object that’s instantiated once to serve the entire application. |
TheSessionFactory produces instances ofSession.Each session should be thought of as representing aunit of work.
sessionFactory.inTransaction(session->{(1)session.persist(newEvent("Our very first event!",now()));(2)session.persist(newEvent("A follow up event",now()));});| 1 | TheinTransaction() method creates a session and starts a new transaction. |
| 2 | Here we create two newEvent objects and hands them over to Hibernate, calling thepersist() method to make these instances persistent.Hibernate is responsible for executing anINSERT statement for eachEvent. |
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 simpleHibernate Query Language (HQL) statement to load all existingEvent objects from the database. |
| 2 | Hibernate generates and executes the appropriateSELECT statement, and then instantiates and populatesEvent objects with the data in the query result set. |
Configure Hibernate usingpersistence.xml
Bootstrap a Jakarta PersistenceEntityManagerFactory
Use annotations to provide mapping information
UseEntityManager to persist and query data
This tutorial is located within the download bundle underentitymanager/.
JPA defines a different bootstrap process, along with a standard configuration file format namedpersistence.xml.In Java™ SE environments the persistence provider (Hibernate) is required to locate every JPA configuration file in the classpath at the pathMETA-INF/persistence.xml.
persistence.xml<persistencexmlns="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-unitname="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 --><propertyname="jakarta.persistence.jdbc.url"value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1"/><propertyname="jakarta.persistence.jdbc.user"value="sa"/><propertyname="jakarta.persistence.jdbc.password"value=""/><!-- Automatically export the schema --><propertyname="jakarta.persistence.schema-generation.database.action"value="create"/><!-- Echo all executed SQL to console --><propertyname="hibernate.show_sql"value="true"/><propertyname="hibernate.format_sql"value="true"/><propertyname="hibernate.highlight_sql"value="true"/></properties></persistence-unit></persistence>| 1 | Apersistence.xml file should provide a unique name for eachpersistence unit it declares.Applications use this name to reference the configuration when obtaining anEntityManagerFactory as we will see shortly. |
| 2 | The<class/> element registers our annotated entity class. |
| 3 | The settings specified as<properties/> elements were already discussed inConfiguration via properties file.Here JPA-standard property names are used where possible. |
Configuration properties prefixed with the legacy Java EE namespace |
The entity class is exactly the same as inThe annotated entity Java class.
The previous tutorials used Hibernate native APIs.This tutorial uses the standard Jakarta Persistence APIs.
protectedvoidsetUp(){entityManagerFactory=Persistence.createEntityManagerFactory("org.hibernate.tutorial.jpa");(1)}| 1 | Notice again that the persistence unit name isorg.hibernate.tutorial.jpa, which matches the name from ourpersistence.xml. |
The code to persist and query entities is almost identical toPersisting entities.Unfortunately,EntityManagerFactory doesn’t have a niceinTransaction() method likeSessionFactory does, so we had to write our own:
voidinTransaction(Consumer<EntityManager>work){EntityManagerentityManager=entityManagerFactory.createEntityManager();EntityTransactiontransaction=entityManager.getTransaction();try{transaction.begin();work.accept(entityManager);transaction.commit();}catch(Exceptione){if(transaction.isActive()){transaction.rollback();}throwe;}finally{entityManager.close();}}If you use JPA in Java SE, you’ll need to copy/paste this function into your project. Alternatively you could unwrap theEntityManagerFactory as aSessionFactory. |
Learn how to use CDI to inject a container-managedEntityManager in Quarkus.Seethe Quarkus website for instructions.
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 underenvers/.
This file is unchanged fromwhat we had before.
The entity class is also almost identical to what we hadpreviously.The major difference is the addition of the annotation@org.hibernate.envers.Audited, which tells Envers to automatically track changes to this entity.
The code saves some entities, makes a change to one of the entities and then uses the Envers API to pull back theinitial revision as well as the updated revision. A revision refers to a historical snapshot of an entity.
org.hibernate.envers.AuditReaderpublicvoidtestBasicUsage(){...AuditReaderreader=AuditReaderFactory.get(entityManager);(1)EventfirstRevision=reader.find(Event.class,2L,1);(2)...EventsecondRevision=reader.find(Event.class,2L,2);(3)...}| 1 | Anorg.hibernate.envers.AuditReader is obtained from theorg.hibernate.envers.AuditReaderFactory which wraps the JPAEntityManager. |
| 2 | Thefind method retrieves specific revisions of the entity. The first call retrieves revision number 1 of theEvent with id 2. |
| 3 | Later, the second call asks for revision number 2 of theEvent with id 2. |
Provide a custom revision entity to additionally capture who made the changes.
Write a query to retrieve only historical data which meets some criteria. Use theUser Guide to see howEnvers queries are constructed.
Experiment with auditing entities which have various forms of relationships (many-to-one, many-to-many, etc). Tryretrieving historical versions (revisions) of such entities and navigating the object tree.
The full list of contributors to Hibernate ORM can be found on theGitHub repository.
The following contributors were involved in this documentation:
Steve Ebersole