work on migration guide and 6.0 announcement

This commit is contained in:
Steve Ebersole 2022-03-30 13:07:22 -05:00
parent 8b9c68b8db
commit cb4691e98e
2 changed files with 330 additions and 298 deletions

View File

@ -1,17 +1,20 @@
= Hibernate 6.0 is Coming
= Hibernate 6.0 Final
Steve Ebersole
:awestruct-tags: ["Hibernate ORM"]
:awestruct-layout: blog-post
:docs-url: https://docs.jboss.org/hibernate/orm/6.0
:javadocs-url: {docs-url}/javadocs
:migration-guide-url: {docs-url}/migration-guide/migration-guide.html
:user-guide-url: {docs-url}/userguide/html_single/Hibernate_User_Guide.html
:jakarta-transformer-url: https://github.com/eclipse/transformer
As Hibernate ORM 6.0 approaches Final, I wanted to take a moment to look back at its origins and
driving forces; and to give insight into why certain choices were made.
It has been years in the making, but ORM 6.0 Final has finally been released!
This post will be followed by a series of more focused posts targeting specific improvements or
cool new features.
This announcement will discuss the major changes as well as give insight into why
certain choices were made.
We will also be following up with a series of more focused posts targeting specific
improvements or cool new features. Stay tuned!
[[api-spi]]
@ -26,14 +29,17 @@ See https://hibernate.org/community/compatibility-policy/ for a discussion of wh
an API versus an SPI.
====
Applications which use only the Jakarta Persistence APIs will be "source compatible" within the
Applications which use only the Jakarta Persistence APIs will be source compatible within the
discussion in <<jpa>>.
Applications using Hibernate APIs will generally be bytecode and source compatible, aside
from the removal of deprecated stuff. There are a few one-off changes that break bytecode and/or
source compatibility; these are covered in the link:{migration-guide-url}[migration guide].
Quite a few SPI changes have changed to support many of the topics discussed here as well as in
One specific change to note is that many of these contracts have been better defined with type
parameters. Theses where inconsistently and sometimes poorly defined in previous versions.
Quite a few SPI contracts have changed to support many of the topics discussed here as well as in
the link:{migration-guide-url}[migration guide]. Many will also be the subject of the mentioned
follow-up posts.
@ -83,7 +89,8 @@ which were later used to access the specific result. We've all seen these "ugly
changes, those select-clause aliases are no longer needed resulting in much more readable generated
SQL.
3. Although we implemented some improved support for limiting needed joins within an entity mapping
(joined inheritance, secondary tables) in 5.x, 6.0 allows even better opportunity for this.
(joined inheritance, secondary tables) in 5.x, 6.0 allows even better opportunity for this. In
fact, the support for this in 5.x was conceptually back-ported from the 6.0 work.
4. (2) and (3) combined results in much smaller SQL needing to be sent to the server which can
have an impact on network communication. Every bit helps.
@ -94,9 +101,22 @@ This was by far the biggest force behind 6.0 initially.
[[mapping-model]]
== Mapping Model
- Object-oriented
- More user-friendly
- Attribute order
The mapping model is an SPI and as such will not be seen by all users. But
it is a major development and impacts many users providing extensions.
The main driving force behind this mapping model work was <<read-by-position>>,
and we had a number of design goals in developing it:
- support positional processing of attributes
- make it object-oriented
- make it user friendly
This model can be accessed though
link:{javadocs-url}/org/hibernate/engine/spi/SessionFactoryImplementor.html#getRuntimeMetamodels()[`RuntimeMetamodelsImplementor`]
which provides access to both:
- The Jakarta Persistence model : link:{javadocs-url}/org/hibernate/metamodel/spi/RuntimeMetamodelsImplementor.html#getJpaMetamodel()[`JpaMetamodelImplementor`]
- Hibernate's mapping model : link:{javadocs-url}/org/hibernate/metamodel/spi/RuntimeMetamodelsImplementor.html#getMappingMetamodel()[`MappingMetamodelImplementor`]
[[annotations]]
@ -118,21 +138,34 @@ This was by far the biggest force behind 6.0 initially.
[[sqm]]
== Semantic Query Model
- HQL and Criteria
- selection of a single entity - de-dup
- set operations (union, intersect, except)
- set aggregations
- window functions
- Functions
- ILIKE support
- improved temporal support (arithmetic, etc)
Hibernate's Semantic Query Model (SQM) is its semantic representation of HQL
and Criteria queries. HQL is interpreted into SQM; Hibernate's Criteria
implementations are SQM nodes.
6.0 implements quite a few changes shared between HQL and Criteria. Most of
these are covered in link:{user-guide-url}#query-language[HQL] and
link:{user-guide-url}#criteria[Criteria] chapters of the User Guide.
Some specific changes include
- Automatic de-duplication of single entity results in a Query. See the link:{migration-guide-url}#query-sqm-rows[Migration Guide] for details
- Set operations (union, intersect, except)
- Set aggregations (listagg, e.g.)
- Window operations (over, e.g.)
- Vastly improved function support. See the link:{user-guide-url}#hql-exp-functions[User Guide] for details.
- ILIKE operator
- Improved temporal support (arithmetic, etc)
[[hql]]
== HQL
- poor and unmaintainable grammars
- Antlr 2 -> Antlr 4
Previous versions of Hibernate used Antlr 2 for parsing. 6.0 updates to Antlr 4 for a few reasons:
- Antlr 2 is no longer supported, and has not for years
- Antlr 4 is faster than Antlr 2
- Antlr 4 grammars are easier to maintain, while the previous Antlr 2 grammars were poorly defined (largely as a function of Antlr 2 itself) and difficult to maintain.
[[criteria]]

View File

@ -60,31 +60,6 @@ As discussed in <<type>> though, this change has a very big impact on Hibernate'
3. Better definition of joins
4. Better determination of unnecessary joins (secondary tables, inheritance tables)
== Bulk SQM against entities mapped to multiple tables
The implementations for bulk SQM DML statements like `insert`, `update` and `delete` were significantly improved in 6.0.
An important bug fix is, that `delete` statements now properly clean up collection tables.
`insert` statements now also support inserting into multi-table entities by making use of special purpose temporary tables
into which the insert goes and is then split up into the respective tables.
There are currently 2 implementation strategies:
* Using temporary tables (the default)
* Using DML in CTEs (used on DB2 and PostgreSQL)
The temporary table approach is pretty simple and works in a similar way to how 5.x already implemented it.
Data or primary key values are first inserted into a temporary table and then the DML changes are applied to the various
tables that are affected by the SQM DML statement.
The CTE approach is new and implements a more performant approach by executing a single statement,
containing the various individual DML statements that would normally be executed separately.
This allows to run SQM DML statements in a single JDBC operation that does not move any data between the database and the application,
which should provide a significant boost for statements that involve many rows.
Note that the configuration property `hibernate.hql.bulk_id_strategy` was changed to `hibernate.query.mutation_strategy`
which will now refer to classes or objects implementing `org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy`.
[[identifier-object]]
== Identifier as Object
@ -322,105 +297,16 @@ To retain backwards compatibility, configure the setting `hibernate.type.preferr
[[query]]
== Query
// todo (6.0) - Query parameter binding overloads accepting `Type`, `BindableType`
// todo (6.0) - addition of parameter binding overloads accepting Class - AttributeConverter, UserType, Java Type (resolved from JavaTypeRegistry), ...
Quite a few changes have been made to how Query works.
[[query-stream]]
=== Stream
`jakarta.persistence.Query#getResultStream()` and `org.hibernate.query.Query#stream()` no longer
return a `Stream` decorator. In order to close the underlying IO resources, it is now necessary to
explicitly call the `Stream#close()` method.
This change makes the Streams returned by Hibernate behave as defined in the JDK
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html[Stream]
documentation, which is quite explicit about the need for an explicit call to `close` by the user
to avoid resource leakages.
[[query-iterate]]
=== Iterate
The `Query#iterate()` method has been removed. The alternative is to use one of
* `Query#stream()`
* `Query#getResultStream()`
* Get the `Iterator` from `List` returned by `Query#list()` / `Query#getResultList()`
[[query-result-cache]]
== Query result cache
Another change in 6.0 is related to the query result cache.
In previous versions, when the query-cache is enabled and a query returning entities is executed, only the entity identifiers were stored in the query-cache. If second-level caching is enabled for a returned entity, the entity data was stored in its second-level cache region.
Storing just the identifiers in the query-cache has a major drawback when fetching is defined for the query (dynamic fetch, entity-graph, etc) as it can, and often does, lead to N+1 selects.
Starting in 6.0, we now store the complete set of data for the entity into the query-cache. This also can have a drawback related to the size of caches. We plan to address this further in later 6.x releases to allow storing just the identifiers along the lines of the previous behavior.
E.g.
```
Statistics stats = sessionFacroty.getStatistics();
// First time the query is executed, query and results are cached and both the query and entity chache will be populated.
TypedQuery<Employee> query = session.createQuery( "select e from Employee e", Employee.class )
.setHint( HINT_CACHEABLE, true );
List<Employee> employees = query.getResultList();
assertEquals( 1, employees.size() );
assertEquals( 0, stats.getQueryCacheHitCount() );
assertEquals( 1, stats.getQueryCacheMissCount() );
assertEquals( 1, stats.getQueryCachePutCount() ); // query cache is populated.
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 1, stats.getSecondLevelCachePutCount() ); // entity cache is populated as well.
stats.clear();
// Second time the same query is executed only the query cache will be hit.
TypedQuery<Employee> query = session.createQuery( "select e from Employee e", Employee.class )
.setHint( HINT_CACHEABLE, true );
List<Employee> employees = query.getResultList();
assertEquals( 1, employees.size() );
assertEquals( 1, stats.getQueryCacheHitCount() ); // the query cache is hit.
assertEquals( 0, stats.getQueryCacheMissCount() );
assertEquals( 0, stats.getQueryCachePutCount() );
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getSecondLevelCachePutCount() ); // No need to hit the entity cache because the query cache contains all the entity data.
```
[[query-sqm]]
== SQM (HQL/Criteria)
=== SQM (HQL/Criteria)
Another major change in 6.0 is the move to a dedicated tree structure to model
HQL and Criteria queries. This tree structure is called the Semantic Query Model, or
SQM for short.
todo (6.0) - cover functions
todo (6.0) - cover new temporal capabilities
todo (6.0) - cover new syntaxes
todo (6.0) - cover bulk manipulation query handling
[[query-criteria-copy]]
== Hibernate Criteria behavior change
By default, when bootstrapping Hibernate through the native bootstrap APIs or when explicitly disabling the newly introduced
`hibernate.criteria.copy_tree` configuration property, it is expected that criteria queries passed to
`jakarta.persistence.EntityManager#createQuery(CriteriaQuery)`, `jakarta.persistence.EntityManager#createQuery(CriteriaUpdate)`
or `jakarta.persistence.EntityManager#createQuery(CriteriaDelete)` are not mutated afterwards to avoid the need for copying the criteria query.
Prior to 6.0, mutations to criteria queries didn't affect `Query` instances created from that.
To retain backwards compatibility, enable the `hibernate.criteria.copy_tree` configuration property.
[[query-sqm-rows]]
==== Result "rows"
@ -433,10 +319,48 @@ The HQL query `select p, a from Person p join p.address a` returns instead a `Li
```
List<Person> result = session.createQuery("from Person p join p.address").list();
List<Object[]> results = session.createQuery("select p, a from Person p join p.address a").list();
List<Object[]> results
```
==== Multi-table Mutation Queries
The implementations for bulk SQM DML statements like `insert`, `update` and `delete` were significantly improved in 6.0.
An important bug fix is, that `delete` statements now properly clean up collection tables.
`insert` statements now also support inserting into multi-table entities by making use of special purpose temporary tables
into which the insert goes and is then split up into the respective tables.
There are currently 2 implementation strategies:
* Using temporary tables (the default)
* Using DML in CTEs (used on DB2 and PostgreSQL)
The temporary table approach is pretty simple and works in a similar way to how 5.x already implemented it.
Data or primary key values are first inserted into a temporary table and then the DML changes are applied to the various
tables that are affected by the SQM DML statement.
The CTE approach is new and implements a more performant approach by executing a single statement,
containing the various individual DML statements that would normally be executed separately.
This allows to run SQM DML statements in a single JDBC operation that does not move any data between the database and the application,
which should provide a significant boost for statements that involve many rows.
Note that the configuration property `hibernate.hql.bulk_id_strategy` was changed to `hibernate.query.mutation_strategy`
which will now refer to classes or objects implementing `org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy`.
[[query-criteria-copy]]
==== Hibernate Criteria behavior change
By default, when bootstrapping Hibernate through the native bootstrap APIs or when explicitly disabling the newly introduced
`hibernate.criteria.copy_tree` configuration property, it is expected that criteria queries passed to
`jakarta.persistence.EntityManager#createQuery(CriteriaQuery)`, `jakarta.persistence.EntityManager#createQuery(CriteriaUpdate)`
or `jakarta.persistence.EntityManager#createQuery(CriteriaDelete)` are not mutated afterwards to avoid the need for copying the criteria query.
Prior to 6.0, mutations to criteria queries didn't affect `Query` instances created from that.
To retain backwards compatibility, enable the `hibernate.criteria.copy_tree` configuration property.
[[query-sqm-pass-thru]]
==== Pass-through tokens
@ -508,7 +432,7 @@ The collection minimum element can be determined by using the `minelement( plura
[[query-native]]
== NativeQuery
=== NativeQuery
As `NativeQuery` extends from `Query`, all the changes listed in <<query>> also apply
to `NativeQuery`.
@ -533,132 +457,79 @@ s.createQuery( "select p from Parent p where id in ?`", Parent.class );
query.setParameter( 1, Arrays.asList( 0, 1, 2, 3 ) );
```
[[proc-call-nativequery]]
=== Callable via NativeQuery
Using `NativeQuery` to call SQL functions and procedures is no longer
supported. `org.hibernate.procedure.ProcedureCall` or
`jakarta.persistence.StoredProcedureQuery` should be used instead.
`@NamedNativeQuery` references defining execution of procedure or
functions should be migrated to use `@NamedStoredProcedureQuery`
instead.
E.g., the following `@NamedNativeQuery` -
```
@NamedNativeQuery(
name = "personAndPhones",
query = "{ ? = call fn_person_and_phones( ? ) }",
callable = true,
resultSetMapping = "personWithPhonesResultMapping"
)
...
final List<Object[]> personAndPhones = entityManager
.createNamedQuery("personAndPhones" )
.setParameter( 1, 1L )
.getResultList();
```
should be changed to use `@NamedStoredProcedureQuery` instead -
```
@NamedStoredProcedureQuery(
name = "personAndPhones",
procedureName = "fn_person_and_phones",
resultSetMappings = "personWithPhonesResultMapping",
hints = @QueryHint(name = "org.hibernate.callableFunction", value = "true"),
parameters = @StoredProcedureParameter(type = Long.class)
)
```
Callable named native queries in hbm.xml files should be migrated to the orm.xml version.
E.g., the following `<sql-query callable="true">` -
```
<sql-query name="simpleScalar" callable="true">
<return-scalar column="name" type="string"/>
<return-scalar column="`value`" type="long"/>
{ ? = call simpleScalar(:number) }
</sql-query>
...
final List<Object[]> results = entityManager
.createNamedQuery("simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
```
should be changed to use `<named-stored-procedure-query/>` instead -
```xml
<named-stored-procedure-query name="simpleScalar" procedure-name="simpleScalar">
<parameter class="java.lang.Integer" mode="IN" name="number"/>
<result-set-mapping>simpleScalar</result-set-mapping>
<hint name="org.hibernate.callableFunction" value="true"/>
</named-stored-procedure-query>
<sql-result-set-mapping name="simpleScalar">
<column-result name="name" class="java.lang.String"/>
<column-result name="value" class="java.lang.Long"/>
</sql-result-set-mapping>
```
TIP: To ease the migration, `<sql-query callable="true"/>` and `@NamedNativeQuery(callable = true)` queries
will be translated and registered as named stored procedure in 6.0, but future versions will drop this automatic translation.
Either `org.hibernate.procedure.ProcedureCall` or `jakarta.persistence.StoredProcedureQuery`
can be used to execute the named query -
```
// Use StoredProcedureQuery
final List<Object[]> personAndPhones = entityManager
.createNamedStoredProcedureQuery( "simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
// Use ProcedureCall
final List<Object[]> personAndPhones = entityManager
.unwrap( Session.class )
.getNamedProcedureCall( "simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
```
It is also no longer supported to execute procedures and functions
via a dynamic (unnamed) `NativeQuery`. All such usages should be converted
to use `ProcedureCall` or `StoredProcedureQuery` instead via
`Session#createStoredProcedureCall` or `EntityManager#createStoredProcedureQuery`,
respectively.
```
// Use StoredProcedureQuery
final List<Object[]> personAndPhones = entityManager
.createStoredProcedureQuery( "fn_person_and_phones", "personWithPhonesResultMapping" )
.setParameter( 1, 1L )
.getResultList();
// Use ProcedureCall
final List<Object[]> personAndPhones = entityManager
.unwrap( Session.class )
.createStoredProcedureCall( "fn_person_and_phones", "personWithPhonesResultMapping" )
.setParameter( 1, 1L )
.getResultList();
```
[[proc-call-param]]
== ProcedureCall / StoredProcedureQuery Parameters
=== ProcedureCall / StoredProcedureQuery Parameters
For parameters defined on a ProcedureCall as accepting binding (IN and INOUT), a distinction is now
made between whether `setParameter` is called or not. If `setParameter` was called, whatever value
was set by the user is passed to the database. If it was not called, Hibernate will not
set any value which triggers the default value defined on the database procedure argument be used
[[query-result-cache]]
=== Query result cache
Another change in 6.0 is related to the query result cache.
In previous versions, when the query-cache is enabled and a query returning entities is executed, only the entity identifiers were stored in the query-cache. If second-level caching is enabled for a returned entity, the entity data was stored in its second-level cache region.
Storing just the identifiers in the query-cache has a major drawback when fetching is defined for the query (dynamic fetch, entity-graph, etc) as it can, and often does, lead to N+1 selects.
Starting in 6.0, we now store the complete set of data for the entity into the query-cache. This also can have a drawback related to the size of caches. We plan to address this further in later 6.x releases to allow storing just the identifiers along the lines of the previous behavior.
E.g.
```
Statistics stats = sessionFacroty.getStatistics();
// First time the query is executed, query and results are cached and both the query and entity chache will be populated.
TypedQuery<Employee> query = session.createQuery( "select e from Employee e", Employee.class )
.setHint( HINT_CACHEABLE, true );
List<Employee> employees = query.getResultList();
assertEquals( 1, employees.size() );
assertEquals( 0, stats.getQueryCacheHitCount() );
assertEquals( 1, stats.getQueryCacheMissCount() );
assertEquals( 1, stats.getQueryCachePutCount() ); // query cache is populated.
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 1, stats.getSecondLevelCachePutCount() ); // entity cache is populated as well.
stats.clear();
// Second time the same query is executed only the query cache will be hit.
TypedQuery<Employee> query = session.createQuery( "select e from Employee e", Employee.class )
.setHint( HINT_CACHEABLE, true );
List<Employee> employees = query.getResultList();
assertEquals( 1, employees.size() );
assertEquals( 1, stats.getQueryCacheHitCount() ); // the query cache is hit.
assertEquals( 0, stats.getQueryCacheMissCount() );
assertEquals( 0, stats.getQueryCachePutCount() );
assertEquals( 0, stats.getSecondLevelCacheHitCount() );
assertEquals( 0, stats.getSecondLevelCacheMissCount() );
assertEquals( 0, stats.getSecondLevelCachePutCount() ); // No need to hit the entity cache because the query cache contains all the entity data.
```
[[query-stream]]
=== Stream
`jakarta.persistence.Query#getResultStream()` and `org.hibernate.query.Query#stream()` no longer
return a `Stream` decorator. In order to close the underlying IO resources, it is now necessary to
explicitly call the `Stream#close()` method.
This change makes the Streams returned by Hibernate behave as defined in the JDK
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html[Stream]
documentation, which is quite explicit about the need for an explicit call to `close` by the user
to avoid resource leakages.
== Interceptor
@ -681,47 +552,6 @@ can lead to situations where a custom Interceptor no longer overrides this metho
of the story... always use `@Override` - this is why it exists
== Removals
=== Legacy Hibernate Criteria API
The legacy Hibernate Criteria API which was deprecated back in Hibernate 5.x and removed in 6.0.
Usually, all queries using the legacy API can be modeled with the JPA Criteria API.
In some cases it is necessary to use the Hibernate JPA Criteria extensions.
=== HQL fetch all properties clause
The `fetch all properties` clause was removed from the HQL language without a replacement.
A similar behavior can be achieved by constructing an entity graph and applying that as load graph:
```java
EntityGraph<Document> entityGraph = entityManager.createEntityGraph( Document.class );
for ( Attribute<Document, ?> attr : entityManager.getMetamodel().entity( Document.class ).getAttributes() ) {
entityGraph.addAttributeNodes( attr.getName() );
}
List<Document> documents = s.createQuery( "from Document", Document.class )
.setHint( "jakarta.persistence.loadgraph", entityGraph )
.getResultList();
```
=== JMX integration
Hibernate no longer provides built-in support for integrating itself with JMX environments.
=== JACC integration
Hibernate no longer provides built-in support for integrating itself with JACC environments.
=== Previously Deprecated features:
* 'hibernate.classLoader.application', 'hibernate.classLoader.resources', 'hibernate.classLoader.hibernate' and 'hibernate.classLoader.environment': use 'hibernate.classLoaders' instead.
* 'hibernate.hbm2dll.create_namespaces': use 'jakarta.persistence.create-database-schemas' or 'hibernate.hbm2ddl.create_namespaces'
// todo (6.0) - surely there are more than this...
== Fetch circularity determination
As back-ground, Hibernate does understand whether a fetch is actually, truly circular. It simply
@ -880,6 +710,10 @@ Consider the following example:
Prior to 6.0, a query would return a list of tuples [`Organization`, `Employee`],
but now this will return a list of `Organization` with an initialized `employments` collection.
== Removals
The following features have been removed
== hbm.xml multiple <column/> now disallowed
In 6.0 the support for basic property mappings with multiple columns was removed. The only use case for that was when a
@ -906,3 +740,168 @@ have to be migrated to proper components:
```
The component class attribute now supports interpreting a `CompositeUserType` class properly.
=== Legacy Hibernate Criteria API
The legacy Hibernate Criteria API which was deprecated back in Hibernate 5.x and removed in 6.0.
Usually, all queries using the legacy API can be modeled with the JPA Criteria API.
In some cases it is necessary to use the Hibernate JPA Criteria extensions.
[[query-iterate]]
=== Iterate
The `Query#iterate()` method has been removed. The alternative is to use one of
* `Query#stream()`
* `Query#getResultStream()`
* Get the `Iterator` from `List` returned by `Query#list()` / `Query#getResultList()`
[[proc-call-nativequery]]
=== Callable via NativeQuery
Using `NativeQuery` to call SQL functions and procedures is no longer
supported. `org.hibernate.procedure.ProcedureCall` or
`jakarta.persistence.StoredProcedureQuery` should be used instead.
`@NamedNativeQuery` references defining execution of procedure or
functions should be migrated to use `@NamedStoredProcedureQuery`
instead.
E.g., the following `@NamedNativeQuery` -
```
@NamedNativeQuery(
name = "personAndPhones",
query = "{ ? = call fn_person_and_phones( ? ) }",
callable = true,
resultSetMapping = "personWithPhonesResultMapping"
)
...
final List<Object[]> personAndPhones = entityManager
.createNamedQuery("personAndPhones" )
.setParameter( 1, 1L )
.getResultList();
```
should be changed to use `@NamedStoredProcedureQuery` instead -
```
@NamedStoredProcedureQuery(
name = "personAndPhones",
procedureName = "fn_person_and_phones",
resultSetMappings = "personWithPhonesResultMapping",
hints = @QueryHint(name = "org.hibernate.callableFunction", value = "true"),
parameters = @StoredProcedureParameter(type = Long.class)
)
```
Callable named native queries in hbm.xml files should be migrated to the orm.xml version.
E.g., the following `<sql-query callable="true">` -
```
<sql-query name="simpleScalar" callable="true">
<return-scalar column="name" type="string"/>
<return-scalar column="`value`" type="long"/>
{ ? = call simpleScalar(:number) }
</sql-query>
...
final List<Object[]> results = entityManager
.createNamedQuery("simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
```
should be changed to use `<named-stored-procedure-query/>` instead -
```xml
<named-stored-procedure-query name="simpleScalar" procedure-name="simpleScalar">
<parameter class="java.lang.Integer" mode="IN" name="number"/>
<result-set-mapping>simpleScalar</result-set-mapping>
<hint name="org.hibernate.callableFunction" value="true"/>
</named-stored-procedure-query>
<sql-result-set-mapping name="simpleScalar">
<column-result name="name" class="java.lang.String"/>
<column-result name="value" class="java.lang.Long"/>
</sql-result-set-mapping>
```
TIP: To ease the migration, `<sql-query callable="true"/>` and `@NamedNativeQuery(callable = true)` queries
will be translated and registered as named stored procedure in 6.0, but future versions will drop this automatic translation.
Either `org.hibernate.procedure.ProcedureCall` or `jakarta.persistence.StoredProcedureQuery`
can be used to execute the named query -
```
// Use StoredProcedureQuery
final List<Object[]> personAndPhones = entityManager
.createNamedStoredProcedureQuery( "simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
// Use ProcedureCall
final List<Object[]> personAndPhones = entityManager
.unwrap( Session.class )
.getNamedProcedureCall( "simpleScalar" )
.setParameter( 1, 1L )
.getResultList();
```
It is also no longer supported to execute procedures and functions
via a dynamic (unnamed) `NativeQuery`. All such usages should be converted
to use `ProcedureCall` or `StoredProcedureQuery` instead via
`Session#createStoredProcedureCall` or `EntityManager#createStoredProcedureQuery`,
respectively.
```
// Use StoredProcedureQuery
final List<Object[]> personAndPhones = entityManager
.createStoredProcedureQuery( "fn_person_and_phones", "personWithPhonesResultMapping" )
.setParameter( 1, 1L )
.getResultList();
// Use ProcedureCall
final List<Object[]> personAndPhones = entityManager
.unwrap( Session.class )
.createStoredProcedureCall( "fn_person_and_phones", "personWithPhonesResultMapping" )
.setParameter( 1, 1L )
.getResultList();
```
=== HQL fetch all properties clause
The `fetch all properties` clause was removed from the HQL language without a replacement.
A similar behavior can be achieved by constructing an entity graph and applying that as load graph:
```java
EntityGraph<Document> entityGraph = entityManager.createEntityGraph( Document.class );
for ( Attribute<Document, ?> attr : entityManager.getMetamodel().entity( Document.class ).getAttributes() ) {
entityGraph.addAttributeNodes( attr.getName() );
}
List<Document> documents = s.createQuery( "from Document", Document.class )
.setHint( "jakarta.persistence.loadgraph", entityGraph )
.getResultList();
```
=== JMX integration
Hibernate no longer provides built-in support for integrating itself with JMX environments.
=== JACC integration
Hibernate no longer provides built-in support for integrating itself with JACC environments.
=== Previously Deprecated features
* 'hibernate.classLoader.application', 'hibernate.classLoader.resources', 'hibernate.classLoader.hibernate' and 'hibernate.classLoader.environment': use 'hibernate.classLoaders' instead.
* 'hibernate.hbm2dll.create_namespaces': use 'jakarta.persistence.create-database-schemas' or 'hibernate.hbm2ddl.create_namespaces'
// todo (6.0) - surely there are more than this...