-
Story
-
Resolution: Done
-
Major
-
None
-
False
-
-
False
-
+
-
---
-
-
This upgrades Quarkus to Hibernate ORM 7.
~Based on #41359, which must be merged first.~ => Done
- Closes: #45164
- Fixes: #43368
- Fixes: #38948
- Closes: #42247
Migration guide entry:
```adoc
== Jakarta Persistence / Hibernate ORM
=== Upgrade to Hibernate ORM 7.0 / Jakarta Persistence 3.2
The Quarkus extension for Hibernate ORM was upgraded to Hibernate ORM 7.0 / Jakarta Persistence 3.2.
Hibernate ORM 7.0 is for the most part backwards-compatible with Hibernate ORM 6.6, and comes with [many improvements and new features, as well as a switch from the LGPL license to ASL 2](https://docs.jboss.org/hibernate/orm/7.0/whats-new/whats-new.html).
However, as with any major version, a few breaking changes are to be expected. Below are the ones most likely to affect existing applications.
Refer to the https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html[Hibernate ORM 7.0 migration guide] for more information.
=== API changes
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#defer-to-jpa[Various deprecated `Session` methods have been removed in favor of JPA equivalents]. In particular: `load(...)` => `getReference(...)`, `get(...)` => `find(...)`, `delete(...)` => `remove(...)`, `save(...)` => `persist(...)`, `update(...)` => `merge(...)`, `saveOrUpdate(...)` => `persist` (new entity)/`merge` (persisted, then detached entity).
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#removal-annotations[Various deprecated annotations methods have been removed in favor of JPA equivalents]. In particular: `@Table` = `@jakarta.persistence.Table`, `@Where`/`@WhereJoinTable` => `@SQLRestriction`/`@SQLJoinTableRestriction`, `@OrderBy` => `@SQLOrder` or `@jakarta.persistence.OrderBy`, `@Index` => `@jakarta.persistence.Index`, `@IndexColumn` => `@OrderColumn`.
- Hibernate's `@Cascade` and `CascadeType` are deprecated in favor of JPA equivalents (e.g. `@OneToMany(cascade = ...)`).
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#proxy-annotation[Proxy customization changed significantly]. If you were using `@Proxy, consider `@ConcreteProxy` instead, or taking advantage of `Session#getReference`/`Hibernate#unproxy` as necessary.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#misc-api[`org.hibernate.Metamodel` was removed] in favor of `org.hibernate.metamodel.model.domain.JpaMetamodel`.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#usertype[`UserType` and `CompositeType` had some method signature change] to no longer refer to internal/SPI types.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#misc-spi[Various JDBC types were moved to an internal package]. Use `@JdbcTypeCode` instead of `@JdbcType` to map your attributes to these types.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#lock-options[`LockOptions` was deprecated]; impacted methods have alternatives involving `LockMode`.
=== Behavior changes
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#model-validation[Many misplaced mapping annotations will now result in an exception], instead of being ignored. This includes for example conflicting `@Basic`/`@ManyToOne` annotations on the same attribute, but also using attribute converters on `@Id`/`@Version`/associations/etc., which was never supported and was effectively ignored.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#stateless-session-cache[`StatelessSession`] now takes advantage of the second-level cache.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#stateless-session-jdbc-batching[`StatelessSession`] no longer complies with [quarkus.hibernate-orm.jdbc.statement-fetch-size](https://quarkus.io/guides/hibernate-orm#quarkus-hibernate-orm_quarkus-hibernate-orm-jdbc-statement-fetch-size). Instead, you can use explicit batch operations such as `insertMultiple()`.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#create-query[Some ambiguous query strings are now disallowed]. This should mainly impact type-unsafe query creation, when not passing a class to `Session#createQuery`, or when using Panache to create a query. Relevant query strings are those without a `select` clause, but with a (non-fetch) join. For example `from Person p left join p.address` should become one of `from Person p`, `select p, a from p left join p.address a`, or `from p left join fetch p.address`, depending on the desired behavior.
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#datetime-native[Native queries now return `java.time` types instead of `java.sql` types for date/time values] in the absence of specific type instructions.
=== DDL/schema changes
Quoting behavior, which suffered from a regression in Hibernate ORM 6.x, was fixed in 7.0 as part of https://hibernate.atlassian.net/browse/HHH-16516[HHH-16516]. Custom database initialization script, in particular on H2, may need to be adapted to avoid use of quotes.
The following changes will require updating the database schema, and manually updating data:
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#array-mapping-changes-on-db2-sap-hana-sql-server-and-sybase-ase[Basic arrays (e.g. `String[]`) are now mapped to proper array structures in database] instead of being serialized as binary data. This behavior can be reverted by setting `quarkus.hibernate-orm.unsupported-properties."hibernate.type.preferred_array_jdbc_type"` to `VARBINARY`.
The following changes should not require a database schema or data update, as SQL generated by Hibernate should to work even with an older schema:
- https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#mysql-varchar[`char`/`Character` attributes are mapped to `varchar(1)`] instead of `char(1)`.
- On Oracle and Microsoft SQL Server, https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#ddl-implicit-datatype-timestamp[timestamp attributes have a different default sub-second precision].
- On Oracle, https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html#float-mapping-changes-oracle[`float`/`double` attributes are mapped to `binary_float`/`binary_double`] instead of `float(p)`/`real`/`double precision` types.
=== Annotation processor artifact relocation
Hibernate ORM 7.0 changes the Maven coordinates of its annotation processor responsible for the generation of the static metamodel and Jakarta Data repositories from `org.hibernate.orm:hibernate-jpamodelgen` to `org.hibernate.orm:hibernate-processor`. Make sure to update your `annotationProcessorPath` in Maven, or `annotationProcessor` instruction in Gradle.
Additionally, the annotation processor `org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor` is now deprecated
in favor of `org.hibernate.processor.HibernateProcessor`. If your build script was explicitly referring to the processor by name, e.g. with the `annotationProcessors` tag of `maven-compiler-plugin`, make sure to replace the deprecated processor name with the new one.
=== CDI restrictions for Hibernate ORM components
Some pluggable components, that are potentially retrieved before CDI is initialized, can no longer be CDI beans. This includes in particular:
- `org.hibernate.type.descriptor.jdbc.JdbcType`
- `org.hibernate.type.descriptor.java.BasicJavaType`
- `org.hibernate.type.descriptor.java.JavaType`
- `org.hibernate.usertype.UserType`
- `org.hibernate.usertype.UserCollectionType`
- `org.hibernate.usertype.CompositeUserType`
- `org.hibernate.type.descriptor.java.MutabilityPlan`
- `org.hibernate.metamodel.spi.EmbeddableInstantiator`
- `org.hibernate.generator.Generator` and its subclasses `org.hibernate.id.IdentifierGenerator`, `org.hibernate.generator.AnnotationBasedGenerator`, etc.
- `org.hibernate.envers.RevisionListener`
If you need to provide a custom implementation of such components, and need access to CDI within that implementation, consider retrieving other beans when first needed, using `Arc.container().instance(OtherBean.class).get()`.
== Elasticsearch
Default connection pool sizes have been bumped https://hibernate.atlassian.net/issues/HSEARCH-5045[to provide a better experience with Hibernate Search], in particular when mass indexing:
- `quarkus.elasticsearch.max-connections` now defaults to `40` instead of `20`.
- `quarkus.elasticsearch.max-connections-per-route` now defaults to `20` instead of `10`.
=== Upgrade to Hibernate Search 8.0
The Quarkus extensions for Hibernate Search were upgraded to Hibernate Search 8.0.
Hibernate ORM 8.0 is for the most part backwards-compatible with Hibernate Search 7.2, and comes with https://hibernate.org/search/releases/8.0/#whats-new[many improvements and new features], in particular a https://hibernate.org/search/releases/8.0/#static-metamodel[static metamodel]
However, as with any major version, a few breaking changes are to be expected.
Below are the ones most likely to affect existing applications.
Refer to the the https://docs.jboss.org/hibernate/search/8.0/migration/html_single/[Hibernate Search 8.0 migration guide] for more information.
- Deprecated classes have been removed in favor of their recommended alternatives, in particular `org.hibernate.search.mapper.orm.massindexing.MassIndexingMonitor` => `org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor`.
- `MassIndexingMonitor#addToTotalCount` is now deprecated in favor of the more flexible `MassIndexingMonitor#typeGroupMonitor(..)`
- `multi()` methods in the projection DSL are deprecated in favor of `.list()`/`.set()`/`sortedSet()`/`collector(...)`.
- Logging categories have been overhauled. See https://docs.jboss.org/hibernate/search/8.0/reference/en-US/html_single/#logging-categories-aggregated[here for a list of available categories]. In particular, the `org.hibernate.search.elasticsearch.request` logging category, used for logging every request sent to Elasticsearch, has been renamed to `org.hibernate.search.elasticsearch.client.request`.
- Many Search DSL interfaces now have an extra `SR` type argument to accomodate for the new static metamodel. This mostly affects `*Step` interfaces which should generally not be used in application code.
- The format of mass indexing logs has changed – for the better, as more information is presented in a more condensed format.
== Dev Services
Several Dev Services default images have been updated:
- Elasticsearch from 8.18 to 9.0
- OpenSearch from 2.16 to 3.0
NOTE: You can configure Quarkus explicitly to use a specific image for each Dev Service, e.g. see https://quarkus.io/guides/elasticsearch-dev-services#configuring-the-image[here for Elasticsearch/OpenSearch].
```
Status / next steps:
- [x] Make it compile
- [x] Make Java-only, ORM-only tests pass
- [x] Make Kotlin ORM-only tests pass (requires https://github.com/hibernate/hibernate-models/issues/99)
- [x] Upgrade to compatible Search/Reactive versions
- [x] Make Search/Reactive tests pass
- [x] If necessary, upgrade to compatible Validator version
- [x] Inspect commits for temporary workarounds (mentions of `HHH-`) and remove them if they are no longer necessary – see in particular https://hibernate.atlassian.net/browse/HHH-19033
- [x] Inspect commits + [upstream migration guide](https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html) and write migration notes for Quarkus (ping Guillaume so he can assess the situation)
- [ ] Inspect commits + [upstream migration guide](https://docs.jboss.org/hibernate/orm/7.0/migration-guide/migration-guide.html) and write [OpenRewrite recipes in `quarkus-update`](https://github.com/quarkusio/quarkus-updates/tree/main/recipes/src/main/resources/quarkus-updates/core)
- [x] Upgrade to Final versions
- [x] Link to fixed Quarkus issues in this PR – see https://github.com/quarkusio/quarkus/issues?q=is%3Aissue%20is%3Aopen%20label%3Aarea%2Fhibernate-orm%2Carea%2Fhibernate-reactive%2Carea%2Fhibernate-search%20label%3Akind%2Fbug-thirdparty
- [x] Check whether #45263 gets fixed by the Hibernate Reactive update, because Hibernate Reactive is now much more similar to ORM when it comes to DB version setting/checking. If relevant, consider documenting DB version setting/checking for Hibernate Reactive. => Moved to #43764
- [x] Make sure to support injecting `jakarta.persistence.SchemaManager` – see https://github.com/quarkusio/quarkus/pull/47792
- [x] Take Elasticsearch upgrades into account in migration guide