** `Transaction#getTimeout`. JPA 3.2 adds `#getTimeout` but uses `Integer` whereas Hibernate has historically used `int`. Note that this raises the possibility of a `NullPointerException` during migration if, e.g., performing direct comparisons on the timeout value against an in (auto unboxing).
== Queries with implicit `select` list and no explicit result type
In previous versions, Hibernate allowed a query with no `select` list to be passed to the overload of `createQuery()` with no explicit result type parameter, for example:
[source,java]
List query =
session.createQuery("from X, Y")
.getResultList()
or:
[source,java]
List query =
session.createQuery("from X join y")
.getResultList()
The select list was inferred based on the `from` clause.
In Hibernate 6 we decided to deprecate this overload of `createQuery()`, since:
- it returns a raw type, resulting in compiler warnings in client code, and
- the second query is truly ambiguous, with no obviously intuitive interpretation.
As of Hibernate 7, the method is remains deprecated, and potentially-ambiguous queries _are no longer accepted_.
Migration paths include:
1. explicitly specify the `select` list,
2. add `X.class` or `Object[].class` as a second argument, to disambiguate the interpretation of the query, or
3. in the case where the query should return exactly one entity, explicitly assign the alias `this` to that entity.
For example, the queries above may be migrated via:
The removal of `CascadeType.SAVE_UPDATE` slightly changes the persist and flush behaviour to conform with Jakarta Persistence.
Persisting a transient entity or flushing a manged entity with an associated detached entity having the association annotated with `cascade = CascadeType.ALL` or `cascade = CascadeType.PERSIST` throws now an `jakarta.persistence.EntityExistsException` if the detached entity has not been re-associated with the Session.
To re-associate the detached entity with the Session the `Session#merge` method can be used.
Assuming we have `c1` as a detached `Child`, the following code will now result in `jakarta.persistence.EntityExistsException` being thrown at flush time:
Traditionally, Hibernate allowed detached entities to be refreshed. However, Jakarta Persistence prohibits this practice and specifies that an `IllegalArgumentException` should be thrown instead. Hibernate now fully aligns with the JPA specification in this regard.
Along the same line of thought, also acquiring a lock on a detached entity is no longer allowed.
To this effect the `hibernate.allow_refresh_detached_entity`, which allowed Hibernate's legacy refresh behaviour to be invoked, has been removed.
In the absence of a `@SqlResultSetMapping`, previous versions of Hibernate used `java.sql` types (`Date`, `Time`, `Timestamp`) to represent date/time types returned by a native query.
In 7.0, such queries return types defined by `java.time` (`LocalDate`, `LocalTime`, `LocalDateTime`) by default.
The previous behavior may be recovered by setting `hibernate.query.native.prefer_jdbc_datetime_types` to `true`.
The signature of the `Configurable#configure` method changed from accepting just a `ServiceRegistry` instance to the new `GeneratorCreationContext` interface, which exposes a lot more useful information when configuring the generator itself. The old signature has been deprecated for removal, so you should migrate any custom `Configurable` generator implementation to the new one.
Automatic JDBC batching has the side effect of delaying the execution of the batched operation, and this undermines the synchronous nature of operations performed through a stateless session.
In Hibernate 7, the configuration property `hibernate.jdbc.batch_size` now has no effect on a stateless session.
Automatic batching may be enabled by explicitly calling `setJdbcBatchSize()`.
However, the preferred approach is to explicitly batch operations via `insertMultiple()`, `updateMultiple()`, or `deleteMultiple()`.
== Criteria API and inheritance subtypes attributes
It was previously possible to use the string version of the `jakarta.persistence.criteria.Path#get` and `jakarta.persistence.criteria.From#join` methods with names of attributes defined in an inheritance subtype of the type represented by the path expression. This was handled internally by implicitly treating the path as the subtype which defines said attribute. Since Hibernate 7.0, aligning with the JPA specification, the Criteria API will no longer allow retrieving subtype attributes this way, and it's going to require an explicit `jakarta.persistence.criteria.CriteriaBuilder#treat` to be called on the path first to downcast it to the subtype which defines the attribute.
Implicit treats are still going to be applied when an HQL query dereferences a path belonging to an inheritance subtype.
== `@OrderColumn` in unowned `@OneToMany` associations
In an unowned (`mappedBy`) one-to-many association, an `@OrderColumn` should, in principle, also be mapped by a field of the associated entity, and the value of the order column should be determined by the value of this field, not by the position in the list.
Previously, since version 4.1, https://hibernate.atlassian.net/issues/HHH-18830[Hibernate would issue superfluous SQL `UPDATE` statements] to set the value of the order column based on the state of the unowned collection.
This was incorrect according to the JPA specification, and inconsistent with the natural semantics of Hibernate.
In Hibernate 7, these SQL `UPDATE` statements only occur if the `@OrderColumn` is _not_ also mapped by a field of the entity.
** Removed `org.hibernate.Session#save` in favor of `org.hibernate.Session#persist`
** Removed `org.hibernate.Session#saveOrUpdate` in favor `#persist` if the entity is transient or `#merge` if the entity is detached.
** Removed `org.hibernate.Session#update` in favor of `org.hibernate.Session.merge`
** Removed `org.hibernate.annotations.CascadeType.SAVE_UPDATE` in favor of `org.hibernate.annotations.CascadeType.PERSIST` + `org.hibernate.annotations.CascadeType.MERGE`
** Removed `org.hibernate.Session#delete` in favor of `org.hibernate.Session#remove`
** Removed `org.hibernate.annotations.CascadeType.DELETE` in favor of `org.hibernate.annotations.CascadeType#REMOVE`
** Removed `org.hibernate.Session#refresh(String entityName, Object object)` in favor of `org.hibernate.Session#refresh(Object object)`
** Removed `org.hibernate.Session#refresh(String entityName, Object object, LockOptions lockOptions)` in favor of `org.hibernate.Session#refresh(Object object, LockOptions lockOptions)`
** Removed `org.hibernate.integrator.spi.Integrator#integrate(Metadata,SessionFactoryImplementor,SessionFactoryServiceRegistry)` in favor of `org.hibernate.integrator.spi.Integrator#integrate(Metadata,BootstrapContext,SessionFactoryImplementor)`
** Removed `org.hibernate.Interceptor#onLoad(Object, Serializable, Object[] , String[] , Type[] )` in favour of `org.hibernate.Interceptor#onLoad(Object, Object, Object[], String[], Type[] )`
** Removed `org.hibernate.Interceptor#onSave(Object, Serializable, Object[], String[], Type[])` in favour of `org.hibernate.Interceptor#onSave(Object, Object, Object[], String[], Type[])`
** Removed `org.hibernate.Interceptor#onDelete(Object, Serializable, Object[], String[], Type[])` in favour of `org.hibernate.Interceptor#onDelete(Object, Serializable, Object[], String[], Type[])`
** Removed `org.hibernate.Interceptor#onCollectionRecreate(Object, Serializable)` in favour of `org.hibernate.Interceptor#onCollectionRecreate(Object, Object)`
** Removed `org.hibernate.Interceptor#onCollectionRemove(Object, Serializable)` in favour of `org.hibernate.Interceptor#onCollectionRemove(Object, Object)`
** Removed `org.hibernate.Interceptor#onCollectionUpdate(Object, Serializable)` in favour of `org.hibernate.Interceptor#onCollectionUpdate(Object, Object)`
** Removed `org.hibernate.Interceptor#findDirty(Object, Serializable, Object[], Object[], String[], Type[])` in favour of `org.hibernate.Interceptor#findDirty(Object, Object, Object[], Object[], String[], Type[])`
** Removed `org.hibernate.Interceptor#getEntity(String, Serializable)` in favour of `org.hibernate.Interceptor#getEntity(String, Serializable)`
** Removed `org.hibernate.metamodel.spi.MetamodelImplementor` in favor of `org.hibernate.metamodela.MappingMetmodel` or `org.hibernate.metamodel.model.domain.JpaMetamodel`
** Removed `org.hibernate.Metamodel` in favor of `org.hibernate.metamodel.model.domain.JpaMetamodel`