Hibernate 7 is the latest iteration of one of the most popular Object-Relational Mapping (ORM) frameworks for Java, and it brings a suite of powerful enhancements that make it a must-know tool for modern developers. This tutorial dives into the core features of Hibernate 7, explaining how it builds on its strong foundation to enhance type safety, developer productivity, and persistence layer integration.
Key Features of Hibernate 7
Support for JPA 3.2
Hibernate 7 fully supports the Jakarta Persistence API (JPA) version 3.2, which is a part of the Jakarta EE 10 release. JPA 3.2 offers several improvements, such as better mapping capabilities, enhanced query APIs, and more robust lifecycle management of entities.
Benefits:
- Compatibility: Hibernate 7 ensures seamless integration with Jakarta EE 10 applications.
- Modern APIs: Developers can leverage the latest standards in persistence without needing additional frameworks or tools.
Introduction of Hibernate Data Repositories
One of the standout features of Hibernate 7 is the introduction of Hibernate Data Repositories, which implements the new Jakarta Data specification. This feature enables developers to work with data repositories directly, without relying on external repository frameworks like Spring Data.
What are Hibernate Data Repositories?
- Jakarta Data Integration: They offer native repository support, adhering to the Jakarta Data specification.
- Out-of-the-Box Repositories: Developers can define repository interfaces, and Hibernate generates the implementation automatically.
- Simplified Persistence Layer: The need for custom repository frameworks is eliminated, reducing complexity and improving maintainability.
Enhanced Compile-Time Type Safety
Hibernate 7 introduces a level of compile-time type safety that was not previously possible. This ensures that many common programming errors are caught during development, rather than at runtime.
How It Works:
- Criteria API Improvements: The Criteria API in Hibernate 7 takes advantage of Java’s type system, making queries safer and easier to write.
- Repository Type-Safety: Methods in Hibernate Data Repositories are also type-safe, minimizing runtime errors due to mismatched types.
Seamless ORM-Persistence Integration
Hibernate 7 makes the persistence layer integration smoother than ever. By tightly coupling the ORM with Jakarta Data Repositories, the framework eliminates the need for older add-ons or custom frameworks.
Key Improvements:
- Unified Approach: No need to juggle multiple frameworks for repository management.
- Automatic Query Derivation: Hibernate can derive queries from method names, making data access operations concise.
- Performance Optimizations: Hibernate 7 optimizes the ORM-persistence integration, resulting in faster query execution and reduced overhead.
How to start using Hibernate 7
Hibernate ORM 7.0 is still in development:
- some features may be incomplete;
- newly introduced features may change in a backward-incompatible way before the stable release.
Therefore, one approach to start evaluating the new features is the awesome JBang tool which will let you wet your feet with Hibernate 7 without any extra set up. If you are new to JBang we recommend checking this article: JBang: Create Java scripts like a pro
Here is a sample code which uses some features of Hibernate 7. You can use it as a template to Test or prototype new features of this release:
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.hibernate.orm:hibernate-core:7.0.0.Beta3
//DEPS org.hibernate.validator:hibernate-validator:8.0.1.Final
//DEPS org.glassfish:jakarta.el:4.0.2
//DEPS org.hibernate.orm:hibernate-agroal:7.0.0.Beta3
//DEPS io.agroal:agroal-pool:2.1
//DEPS org.apache.logging.log4j:log4j-core:2.24.1
//DEPS org.hibernate.orm:hibernate-processor:7.0.0.Beta3
//DEPS com.h2database:h2:2.2.224
package com.example;
import org.hibernate.jpa.HibernatePersistenceConfiguration;
import static java.lang.System.out;
import static org.hibernate.cfg.JdbcSettings.*;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
public class Hibernate7 {
public static void main(String[] args) {
var sessionFactory =
new HibernatePersistenceConfiguration("CustomersDB")
.managedClass(Customer.class)
// use H2 in-memory database
.jdbcUrl("jdbc:h2:mem:db1")
.jdbcCredentials("sa", "")
// use Agroal connection pool
.property("hibernate.agroal.maxSize", "20")
// display SQL in console
.showSql(true, true, true)
.createEntityManagerFactory();
// export the inferred database schema
sessionFactory.getSchemaManager().exportMappedObjects(true);
// persist an entity
sessionFactory.inTransaction(session -> {
session.persist(new Customer(1L, "John Doe", "[email protected]"));
});
// query data using HQL
sessionFactory.inSession(session -> {
out.println(session.createSelectionQuery("select id||': '||name||' ('||email||')' from Customer").getSingleResult());
});
// query data using Criteria API
sessionFactory.inSession(session -> {
var builder = sessionFactory.getCriteriaBuilder();
var query = builder.createQuery(String.class);
var customer = query.from(Customer.class);
query.select(builder.concat(
builder.concat(
builder.concat(customer.get("id").as(String.class), builder.literal(": ")),
customer.get("name")),
builder.concat(builder.literal(" ("), builder.concat(customer.get("email"), builder.literal(")")))
));
out.println(session.createSelectionQuery(query).getSingleResult());
});
}
}
@Entity
class Customer {
@Id
Long id;
@NotNull
String name;
String email;
Customer() {}
Customer(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
}
You can run it as follows:
jbang Hibernate7.java
A close look at the features in this example
Entity Manager Factory Setup: Hibernate is configured via a fluent API to manage Customer entities, using an H2 database and Agroal connection pool.
var sessionFactory =
new HibernatePersistenceConfiguration("CustomersDB")
.managedClass(Customer.class) // Entity class to manage
.jdbcUrl("jdbc:h2:mem:db1") // H2 in-memory database
.jdbcCredentials("sa", "") // Username and password
.property("hibernate.agroal.maxSize", "20") // Connection pool size
.showSql(true, true, true) // Show SQL in logs
.createEntityManagerFactory();
Database Schema Export: Hibernate automatically creates a database schema based on the Customer entity.
sessionFactory.getSchemaManager().exportMappedObjects(true);
inTransaction Method
- Purpose: Simplifies working with database transactions.
- What It Does:
- Starts a new transaction.
- Passes a
Sessionto your lambda function. - Commits the transaction when the lambda completes.
- Rolls back the transaction if an exception occurs.
sessionFactory.inTransaction(session -> {
session.persist(new Customer(1L, "John Doe", "[email protected]"));
});
inSession Method
- Purpose: Provides a convenient way to execute read-only operations with a session.
- What It Does:
- Opens a new session.
- Passes the session to your lambda function.
- Automatically closes the session after the lambda completes.
sessionFactory.inSession(session -> {
var result = session.createSelectionQuery("select name from Customer").getSingleResult();
out.println(result);
});
Type safe Criteria API
The new API allows developers to create type-safe queries like this:
sessionFactory.inSession(session -> {
var builder = sessionFactory.getCriteriaBuilder();
var query = builder.createQuery(String.class);
var customer = query.from(Customer.class);
query.select(builder.concat(
builder.concat(
builder.concat(customer.get("id").as(String.class), builder.literal(": ")),
customer.get("name")),
builder.concat(builder.literal(" ("), builder.concat(customer.get("email"), builder.literal(")")))
));
out.println(session.createSelectionQuery(query).getSingleResult());
});
Conclusion
Hibernate 7 simplifies persistence management while leveraging modern Java and Jakarta EE capabilities. With its focus on type safety, developer productivity, and native repository support, it sets a new standard for ORM frameworks.