This guide discusses migration to Hibernate ORM version 7.4. For migration from earlier versions, see any other pertinent migration guides as well.

Requirements

See the website for the list of requirements for the 7.4 series.

New Features

See the website for the list of new features in the 7.4 series.

Changes to API

This section describes changes to contracts (classes, interfaces, methods, etc.) which are considered API.

Changes to SPI

This section describes changes to contracts (classes, interfaces, methods, etc.) which are considered SPI.

Changes in Behavior

This section describes changes in behavior that applications should be aware of.

HQL current date and local date on Oracle

Oracle has no true support for dates. Its current_date function produces a datetime. Starting with this release, the HQL expressions current date and local date translate to trunc(current_date), which zeros out the time part.

MySQL default max fetch depth

Previously, MySQLDialect defined a dialect-level default value of 2 for the hibernate.max_fetch_depth configuration property.

As of Hibernate ORM 7.4, this dialect-specific default has been removed. MySQL now behaves consistently with other dialects and relies on Hibernate’s general defaults or explicit user configuration.

Applications that relied on the previous implicit default should explicitly set hibernate.max_fetch_depth if required.

Join fetching for eager @Any mappings

An @Any discriminated association mapping defaults to fetch=EAGER. Previously, such eager @Any associations were always fetched using a separate SELECT statement, which was inefficient. Eager @Any associations are now join fetched by default when an entity is loaded by id.

Limits and fetch joins

When pagination or a limit is used with a query which fetches a collection, the limit is now processed as part of the SQL query. To recover the previous behavior, set the query hint org.hibernate.limitInMemory.

Schema actions now executed even without mapped entities

Previously, if a persistence unit had no @Entity classes, all schema management actions (including import.sql execution) were silently skipped, even when explicitly configured via hbm2ddl.auto or jakarta.persistence.schema-generation.database.action.

As of Hibernate 7.4, schema actions are now processed regardless of whether any entities are mapped. This is the correct behavior, but it means that applications which have an import.sql file on the classpath by accident may now see it executed when it was previously ignored.

Migration of Spanner PostgreSQL Dialect to core

The SpannerPostgreSQLDialect, which was previously part of the hibernate-community-dialects artifact under the package name org.hibernate.community.dialect, has been migrated to the hibernate-core artifact and package name org.hibernate.dialect.

Users currently using the community dialect must update their dialect configuration to use org.hibernate.dialect.SpannerPostgreSQLDialect (or rely on Hibernate’s automatic dialect resolution).

Changes to DDL generation

This section describes changes to DDL generated by the schema export tooling. Such changes typically do not impact programs using a relational schema managed externally to Hibernate.

Unique constraints for @ElementCollection sets

A unique constraint is now added to the table mapped by an @ElementCollection set where appropriate.

@CreationTimestamp and @UpdateTimestamp columns inferred not-null

A column mapped by a @CreationTimestamp or @UpdateTimestamp generator now has a NOT NULL constraint added automatically.

Optional: Migrating from Hibernate Envers to core @Audited

This migration is entirely optional. Hibernate Envers continues to work as before in 7.4. However, if you wish to take advantage of the new core @Audited functionality, this section describes the steps involved.

The new core audit support provides very similar functionality to Envers with a simpler programming model: you can use standard Session APIs (and even HQL queries!) within a temporal session opened via atChangeset(), or the more specialized AuditLog functionality, to access the audit logs of your entities.

Annotation changes

Envers Core

@org.hibernate.envers.Audited

@org.hibernate.annotations.Audited

@org.hibernate.envers.NotAudited

@org.hibernate.annotations.Audited.Excluded

@org.hibernate.envers.RevisionEntity

@org.hibernate.annotations.Changelog

@org.hibernate.envers.RevisionNumber

@org.hibernate.annotations.Changelog.ChangesetId

@org.hibernate.envers.RevisionTimestamp

@org.hibernate.annotations.Changelog.Timestamp

RevisionListener

org.hibernate.audit.ChangesetListener (method: newChangeset())

EntityTrackingRevisionListener

org.hibernate.audit.EntityTrackingChangesetListener

Map your REVINFO table

Define a @Changelog entity that maps to the existing REVINFO table (or use the built-in DefaultChangelog):

@Entity
@Table(name = "REVINFO")
@Changelog(listener = MyChangesetListener.class)
public class MyRevision extends ChangelogMapping { ... }

API changes

Envers Core

AuditReader.find(Foo.class, id, rev)

auditLog.find(Foo.class, id, rev) or sf.withOptions().atChangeset(rev).openSession().find(Foo.class, id)

reader.getRevisions(Foo.class, id)

auditLog.getChangesets(Foo.class, id)

reader.getRevisionDate(rev)

auditLog.getChangesetTimestamp(rev)

reader.findRevision(RevInfo.class, rev)

auditLog.findChangeset(RevInfo.class, rev)

reader.createQuery().forEntitiesAtRevision(…​)

HQL in atChangeset() session

reader.createQuery().forRevisionsOfEntity(…​)

auditLog.getHistory(Foo.class, id)

Custom AuditQuery criteria

HQL with changesetId() / modificationType() functions

Schema compatibility

No DDL changes are needed. The default REV/REVTYPE column names and encoding match between Envers and core. The REVINFO table rows continue the same sequence.

Changes in Dependencies

This section describes changes to dependencies used by Hibernate ORM.