6.5 brings many new features, in addition to many improvements and fixes.
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,
hibernate.type.prefer_java_type_jdbc_types=true
See the setting Javadoc for additional details.
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 With |
A Java record can now be used as an @IdClass
record PK(Integer key1, Integer key2) {}
@Entity
@IdClass(PK.class)
class AnEntity {
@Id Integer key1;
@Id Integer key2;
...
}
Filters can now be automatically enabled for each Session and StatelessSession
@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.
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 {
...
}
UPDATE and DELETE queries can now use joins, e.g.
delete from Person p where p.association.someAttr = 1
Manually assigned identifier values can now be used with custom a Generator
thanks to the new allowAssignedIdentifiers()
method.
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);
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. |
Query query = session.createQuery("from Person");
int results = query.getResultCount();
As an incubating feature, 6.5 offers support for key-based pagination (sometimes called "keyset" pagination) via both SelectionQuery
and generated query methods.
Please see the Javadoc for KeyedPage
and KeyedResultList
for more information.
Both HQL and Criteria now support an optional ON CONFLICT clause to allow controlling what should happen when a constraint violation occurs, e.g.
insert into Person (id, name)
values (1, 'John')
on conflict do nothing
See the User Guide for more details.
StatelessSession
now supports filters and SQL logging