2024-03-20 13:27:48 -04:00
= Hibernate 6.5.0.CR1
Steve Ebersole
:awestruct-tags: ["Hibernate ORM", "Releases"]
:awestruct-layout: blog-post
:family: 6.5
:docs-url: https://docs.jboss.org/hibernate/orm/{family}
:javadocs-url: {docs-url}/javadocs
:migration-guide-url: {docs-url}/migration-guide/migration-guide.html
:intro-guide-url: {docs-url}/introduction/html_single/Hibernate_Introduction.html
:user-guide-url: {docs-url}/userguide/html_single/Hibernate_User_Guide.html
:ql-guide-url: {docs-url}/querylanguage/html_single/Hibernate_Query_Language.html
6.5 brings many new features, in addition to many improvements and fixes.
[[java-time]]
== Java Time Handling
Java Time objects can now be directly marshalled through the JDBC driver as defined by JDBC 4.2.
In previous versions, Hibernate would handle Java Time objects using `java.sql.Date`, `java.sql.Time` or
`java.sql.Timestamp` references as intermediate forms.
Another behavioral change with this is handling for timezones. `OffsetDateTime`, `OffsetTime` and
`ZonedDateTime` all encode explicit timezone information. With direct marshalling, Hibernate simply
passes along the value as-is. In the legacy behavior, since the `java.sql` variants do not
encode timezone information, Hibernate generally has to specially handle timezones when converting to
those intermediate forms.
For 6.5 this behavior is disabled by default. To opt-in,
[source,properties]
----
hibernate.type.prefer_java_type_jdbc_types=true
----
See the link:{javadocs-url}/org/hibernate/cfg/MappingSettings.html#PREFER_JAVA_TYPE_JDBC_TYPES[setting Javadoc] for additional details.
[[query-cache-layout]]
== Configurable Query Cache Layout
In Hibernate ORM 6.0 the query cache layout changed from a "shallow" representation of entities and collections,
to a "full" representation. This was done to support re-materializing join fetched data from the query cache data
without hitting the database. Storing the full data in the query cache leads to a higher memory consumption,
which in turn might also hurt application throughput due to a higher garbage collection activity.
6.5 adds the ability to configure the format in which query results are stored in the query cache, either
* globally via the `hibernate.cache.query_cache_layout` setting
* per entity or collection via the `@QueryCacheLayout` annotation
The global `hibernate.cache.query_cache_layout` setting defaults to the `AUTO` value,
which will automatically choose `SHALLOW` or `FULL` for an entity/collection,
depending on whether the entity/collection is cacheable.
Applications that want to retain the `FULL` cache layout that Hibernate ORM 6.0 used should configure
the global property `hibernate.cache.query_cache_layout=FULL`.
Applications that want the cache layout that Hibernate ORM 5 and older versions used should configure
the global property `hibernate.cache.query_cache_layout=SHALLOW`.
[NOTE]
====
Even with the `SHALLOW` cache layout, the association eagerness implied through join fetches will be respected,
and associations will be eagerly initialized. So there is no change of behavior when choosing a different cache layout.
With `SHALLOW`, Hibernate might need to hit the database to materialize the associated data *if it does not exist in the second level cache*.
====
[[record-as-idclass]]
== Allow Java record as @IdClass
A Java record can now be used as an `@IdClass`
[source,java]
----
record PK(Integer key1, Integer key2) {}
@Entity
@IdClass(PK.class)
class AnEntity {
@Id Integer key1;
@Id Integer key2;
...
}
----
2024-03-20 17:35:03 -04:00
[[auto-filters]]
== Support for Auto Enabled Filters
Filters can now be automatically enabled for each Session and StatelessSession
[source,java]
----
@FilterDef(
name="active-filter",
condition="status = true",
autoEnabled=true
)
@Filter(name="active-filter")
@Entity
class DeletableEntity {
...
}
----
Can be combined with the ability to dynamically resolve condition parameters, e.g.
[source,java]
----
class TenantIdResolver implements Supplier<String> {
@Override
public String get() {
return SomeContext.determineTenantId();
}
}
@FilterDef(
name="tenancy-filter",
condition="tenant_id = :tenantId",
autoEnabled=true,
parameter = @ParamDef(
name="tenantId",
type=String.class,
resolver=TenantIdResolver.class
)
)
@Filter(name="tenancy-filter")
@Entity
class SensitiveData {
...
}
----
2024-03-20 13:27:48 -04:00
[[sqm-mutation-joins]]
== Joined Mutation Queries
UPDATE and DELETE queries can now use joins, e.g.
[source]
----
delete from Person p where p.association.someAttr = 1
----
[[manually-assigned-generated-ids]]
2024-03-22 08:27:32 -04:00
== Manually Assigned Identifiers with custom `Generator`
2024-03-20 13:27:48 -04:00
2024-03-21 10:23:08 -04:00
Manually assigned identifier values can now be used with custom a `Generator` thanks to the new `allowAssignedIdentifiers()` method.
2024-03-20 13:27:48 -04:00
[source,java]
----
2024-03-21 10:23:08 -04:00
class MyIdGenerator implements Generator {
2024-03-21 08:11:36 -04:00
...
@Override public boolean allowAssignedIdentifiers() {
return true;
}
}
2024-03-21 10:23:08 -04:00
@IdGeneratorType(MyIdGenerator.class)
@Target({METHOD, FIELD})
@Retention(RUNTIME)
@interface MyGeneratedId {
}
2024-03-20 13:27:48 -04:00
@Entity
class Book {
2024-03-21 10:23:08 -04:00
@Id @MyGeneratedId
2024-03-20 13:27:48 -04:00
Integer id;
...
}
Book book = new Book(1,...)
session.persist(book);
----
[[query-result-count]]
== SelectionQuery.getResultCount()
Selection queries now have the ability to report the number of results there will
be in the final result.
IMPORTANT: This triggers a query against the database.
[source,java]
----
Query query = session.createQuery("from Person");
int results = query.getResultCount();
----
[[key-pagination]]
== Key-based Pagination
2024-03-20 13:54:15 -04:00
As an incubating feature, 6.5 offers support for link:{intro-guide-url}#key-based-pagination[key-based pagination] (sometimes called "keyset" pagination) via both `SelectionQuery` and link:{intro-guide-url}#key-based-paging[generated query methods].
2024-03-20 13:27:48 -04:00
2024-03-20 13:54:15 -04:00
Please see the Javadoc for link:{javadocs-url}/org/hibernate/query/KeyedPage.html[`KeyedPage`] and link:{javadocs-url}/org/hibernate/query/KeyedResultList.html[`KeyedResultList`] for more information.
2024-03-20 13:27:48 -04:00
[[on-conflict]]
== ON CONFLICT Clause for Insert Queries
Both HQL and Criteria now support an optional ON CONFLICT clause to allow controlling what
should happen when a constraint violation occurs, e.g.
[source]
----
insert into Person (id, name)
values (1, 'John')
on conflict do nothing
----
See the link:{user-guide-url}#hql-insert[User Guide] for more details.
[[stateless-session]]
== Work on StatelessSession
`StatelessSession` now supports https://hibernate.atlassian.net/browse/HHH-17620[filters] and https://hibernate.atlassian.net/browse/HHH-17673[SQL logging]
[[jakarta-data]]
== Jakarta Data
6.5 also includes a tech preview of Jakarta Data based on the Hibernate annotation processor.