= 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; ... } ---- [[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 { @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 { ... } ---- [[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]] == Manually Assigned Identifiers with custom `Generator` Manually assigned identifier values can now be used with custom a `Generator` thanks to the new `allowAssignedIdentifiers()` method. [source,java] ---- class MyIdGenerator implements Generator { ... @Override public boolean allowAssignedIdentifiers() { return true; } } @IdGeneratorType(MyIdGenerator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) @interface MyGeneratedId { } @Entity class Book { @Id @MyGeneratedId 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 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]. 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. [[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.