This guide discusses migration to Hibernate ORM version 6.2. For migration from earlier versions, see any other pertinent migration guides as well.
DDL type changes
UUID mapping changes on MariaDB
On MariaDB, the type code SqlTypes.UUID
now by default refers to the DDL type uuid
, whereas before it was using binary(16)
.
Due to this change, schema validation errors could occur on existing databases.
The migration to uuid
requires a migration expression like cast(old as uuid)
.
To retain backwards compatibility, configure the setting hibernate.type.preferred_uuid_jdbc_type
to BINARY
.
UUID mapping changes on SQL Server
On SQL Server, the type code SqlTypes.UUID
now by default refers to the DDL type uniqueidentifier
, whereas before it was using binary(16)
.
Due to this change, schema validation errors could occur on existing databases.
The migration to uuid
requires a migration expression like cast(old as uuid)
.
To retain backwards compatibility, configure the setting hibernate.type.preferred_uuid_jdbc_type
to BINARY
.
JSON mapping changes on Oracle
On Oracle 12.1+, the type code SqlTypes.JSON
now by default refers to the DDL type blob
and on 21+ to json
, whereas before it was using clob
.
Due to this change, schema validation errors could occur on existing databases.
The migration to blob
and json
requires a migration expression like cast(old as blob)
and cast(old as json)
respectively.
To get the old behavior, annotate the column with @Column(definition = "clob")
.
This change was done because blob
and json
are way more efficient and because we don’t expect wide usage of SqlTypes.JSON
yet.
Datatype for enums
Hibernate 6.1 changed the implicit SQL datatype for mapping enums from TINYINT
to SMALLINT
to account for
Java supporting up to 32K enum entries which would overflow a TINYINT
. However, almost no one is developing
enums with that many entries. Starting in 6.2, the choice of implicit SQL datatype for storing enums is sensitive
to the number of entries defined on the enum class. Enums with more than 128 entries are stored as SMALLINT
implicitly,
otherwise TINYINT
is used.
- NOTE
-
On MySQL, enums are now stored using the
ENUM
datatype by default
Timezone and offset storage
OffsetDateTime
and ZonedDateTime
now always map to TIMESTAMP WITH TIME ZONE
by default
Check constraints for boolean and enum mappings
Check constraints now correctly generated for boolean and enum mappings
UNIQUE constraint for optional one-to-one mappings
Previous versions of Hibernate did not create a UNIQUE constraint on the database for logical[1] one-to-one associations marked as optional. That is not correct from a modeling perspective as the foreign-key should be constrained as unique. Starting in 6.2, those UNIQUE constraints are now created.
If this causes problems for an application, creation of the UNIQUE constraint can be skipped
using @jakarta.persistence.ForeignKey(NO_CONSTRAINT)
.
Often the association can also be remapped using @ManyToOne
+ @UniqueConstraint
instead.
Column type inference for number(n,0)
in native SQL queries on Oracle
Since Hibernate 6.0, columns of type number
with scale 0 on Oracle were interpreted as boolean
, tinyint
, smallint
, int
, or bigint
,
depending on the precision.
Now, columns of type number
with scale 0 are interpreted as int
or bigint
depending on the precision.
Removal of support for legacy database versions
This version introduces the concept of minimum supported database version for most of the database dialects that Hibernate supports. This implies that the legacy code for versions that are no longer supported by their vendors, has been removed from the hibernate-core module. It is, however, still available in the hibernate-community-dialects module.
The minimum supported dialect versions are as follows:
Dialect | Minimum supported version |
---|---|
MySQL |
5.7 |
SQL Server 2008 |
10.0 |
DB2 |
10.5 |
DB2i |
7.1 |
DB2z |
12.1 |
MariaDB |
10.3 |
H2 |
1.4.197 |
Derby |
10.14.2 |
Sybase |
16.0 |
CockroachDB |
21.1 |
PostgreSQL |
10.0 |
Oracle |
11.2 |
HSQLDB |
2.6.1 |
Change enhancement defaults and deprecation
The enableLazyInitialization
and enableDirtyTracking
enhancement tooling options in the ANT task, Maven Plugin and Gradle Plugin,
as well as the respective hibernate.enhancer.enableLazyInitialization
and hibernate.enhancer.enableDirtyTracking
configuration settings,
switched their default values to true
and the settings are now deprecated for removal without replacement.
See HHH-15641 for details.
The global property hibernate.bytecode.use_reflection_optimizer
switched the default value to true
and the setting is now deprecated for removal without replacement. See HHH-15631 for details.
API / SPI / Internal distinction
Dating back to Hibernate 5.x, we have been cleaning up packages to make the distinction between contracts which are considered an API, SPI and internal. We’ve done some more work on that in 6.2 as well.
org.hibernate.cfg package
The org.hibernate.cfg
package has been especially egregious in mixing APIs and internals historically. The only
true API contracts in this package include org.hibernate.cfg.AvailableSettings
and org.hibernate.cfg.Configuration
which have been left in place.
Additionally, while it is considered an internal detail, org.hibernate.cfg.Environment
has also been left in place
as many applications have historically used it rather than org.hibernate.cfg.AvailableSettings
.
A number of contracts are considered deprecated and have been left in place.
The rest have been moved under the org.hibernate.boot
package where they more properly belong.
org.hibernate.loader package
Most of the org.hibernate.loader
package is really an SPI centered around org.hibernate.loader.ast
which supports loading entities and collections by various types of keys - primary-key, unique-key,
foreign-key and natural-key. org.hibernate.loader.ast
has already been previously well-defined
in terms of SPI / internal split.
Changes in integration contracts (SPIs)
SPI is a category of interfaces that we strive to maintain with more stability than internal APIs, but which might change from minor to minor upgrades as the project needs a bit of flexibility.
These are not considered public API so should not affect end-user (application developer’s) code but such changes might break integration with other libraries which integrate with Hibernate ORM.
During the development of Hibernate ORM 6.2 the following SPIs have seen some modifications:
EntityPersister#lock
Changed from EntityPersister#lock(Object, Object, Object, LockMode, SharedSessionContractImplementor)
to EntityPersister#lock(Object, Object, Object, LockMode, EventSource)
.
This should be trivial to fix as EventSource
and SharedSessionContractImplementor
are both contracts of the SessionImpl
; to help transition we recommend using
the methods isEventSource
and asEventSource
, available on the `SharedSessionContractImplementor`contract.
N.B. method asEventSource
will throw an exception for non-compatible type; but because of previous restrictions all invocations to lock
actually had to be compatible:
this is now made cleared with the signature change.
EntityPersister#multiLoad
The same change was applieed to multiLoad(Object[] ids, SharedSessionContractImplementor session, MultiIdLoadOptions loadOptions)
,
now migrated to multiLoad(Object[] ids, EventSource session, MultiIdLoadOptions loadOptions)
The same conversion can be safely applied.
Executable#afterDeserialize
As in the previous two cases, the parameter now accepts EventSource
instead of SharedSessionContractImplementor
.
The same conversion can be safely applied.
JdbcType#getJdbcRecommendedJavaTypeMapping()
The return type of JdbcType#getJdbcRecommendedJavaTypeMapping()
was changed from BasicJavaType
to JavaType
.
Even though this is a source compatible change, it breaks binary backwards compatibility.
We decided that it is fine to do this though, as this is a new minor version.