hibernate-orm/migration-guide.adoc

268 lines
8.1 KiB
Plaintext
Raw Normal View History

2020-04-01 14:47:41 -04:00
= 6.0 Migration Guide
2015-08-20 15:29:48 -04:00
:toc:
2020-04-01 14:47:41 -04:00
This guide discusses migration from Hibernate ORM version 6.0. For migration from
2015-08-20 15:29:48 -04:00
earlier versions, see any other pertinent migration guides as well.
== Background
2018-01-17 23:02:35 -05:00
== Known changes
=== Jakarta Persistence
6.0 moves from Java Persistence as defined by the Java EE specs to
Jakarta Persistence as defined by the Jakarta EE spec. The most immediate
impact of this change is that applications would need to be updated to use
the Jakarata Persistence classes (`jakarta.persistence.*`) instead of the Java
Persistence ones (`javax.persistence.*`).
The Jakarta spec also renames the JPA settings (again, from `javax.persistence.*` to
'jakarta.persistence.*') and defines a new set of XSD namespaces for `orm.xml` and
`persistence.xml` files.
Jakarta provides a https://github.com/eclipse/transformer[transformer]
tool which, along with appropriate "rules", will transform a project from Java Persistence to
Jakarta Persistence. This can update package names in source, settings, xsd references and more.
// todo (6.0) : reference to `${root}/rules ?
NOTE: As far as the XSD and setting changes, Hibernate does support both sets as a temporary aid
in migration. It logs a deprecation warning when the Java EE variants are used.
=== Reading from JDBC
Read-by-position rather than read-by-name
2020-04-01 14:47:41 -04:00
=== Type system / custom types
==== Type changes
* The default type for `Duration` was changed to `NUMERIC` which could lead to schema validation errors
==== Influencing JdbcTypeDescriptor to use
Discuss `JdbcTypeCode`, `JdbcType`, `JdbcTypeRegistration`
==== Influencing JavaTypeDescriptor to use
Discuss `@JavaType`, `@JavaTypeRegistration`
==== Component Mapping
Multiple component mappings for the same java class with different property mappings is not supported anymore. Every property mapping combination should have its own java class"
2021-09-28 02:15:07 -04:00
=== Procedure Parameters, enable passing nulls
Passing null or not is now triggered by whether setting the parameter was called at all. In other ords a distinction is made between calling `setParameter` passing null versus not calling `setParameter` at all. In the first case, we pass along the null value; in the second we do not.
2021-11-17 05:06:01 -05:00
=== Query
=== HQL results
2021-11-24 12:21:29 -05:00
HQL queries that use joins without specifying a select clause e.g. `from Person p join p.address` do not return a `List<Object[]>` with an entry per join anymore, but a list of `Person`.
2021-11-17 05:06:01 -05:00
2021-11-24 12:21:29 -05:00
The HQL query `select p,a from Person p join p.address a` returns instead a `List<Object[]>`.
2021-11-17 05:06:01 -05:00
e.g.
```
@Entity
class Person {
...
@ManyToOne
Address address
...
}
@Entity
class Address {
...
}
2021-11-24 12:21:29 -05:00
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();
2021-11-17 05:06:01 -05:00
```
2021-11-24 12:21:29 -05:00
==== Stream
`jakarta.persistence.Query#getResultStream()` and `org.hibernate.query.Query#stream()` do not return a `Stream` decorator anymore, so in order to close the underlying IO resources is now necessary to explicitly call the `Stream#close()` method. The JDK `Stream` documentation is quite explicit about the need for an explicit call to `close` by the user to avoid resource leakages, so we build upon this requirement.
2021-11-17 05:06:01 -05:00
==== Iterate
2021-11-24 12:21:29 -05:00
The `Query#iterate()` method has been removed. The alternative is to use `Query#stream()` or `Query#getResultStream()`.
2021-11-17 05:06:01 -05:00
=== Native Query
==== Native query as a function call is no longer supported.
Given the `NamedNativeQuery`
```
@NamedNativeQuery(
name = "fn_person_and_phones",
query = "{ ? = call fn_person_and_phones( ? ) }",
callable = true,
resultSetMapping = "person_with_phones"
)
```
the code
```
scope.inTransaction(
entityManager -> {
try {
List<Object[]> postAndComments = entityManager.createNamedQuery("fn_person_and_phones" ).setParameter( 1, 1L ).getResultList();
```
is going to throw an `IllegalArgumentException`.
The migration code is
```
List<Object[]> postAndComments = entityManager.createStoredProcedureQuery( "fn_person_and_phones", "person_with_phones" ).setParameter( 1, 1L ).getResultList();
```
2020-04-01 14:47:41 -04:00
=== SQM
2020-04-01 14:47:41 -04:00
* Functions
* Multi-table bulk manipulation HQL/Criteria query handling
* Handle quoted identifiers in HQL and the Ordering parser * Switch from the "expression" to "expressionOrPredicate" rule in the HQL grammar where it makes sense as required by some HQL tests * Cleanup parser rule ordering to allow more keywords in the identifier rule * Implement literal support for Ordering parser * Add special AvgFunction as needed by H2, HSQL, DB2, SQL Server and Sybase that casts arguments to double if necessary * Fix wrong deduplication of order by fragments in case a plural attribute is fetched multiple times * Implement support for de-referencing any-valued mappings in HQL * Avoid unnecessary entity subtypes in polymorphic splitted queries if a base type also matches the requested type * Implement pagination support for polymorphic splitted queries * Cleanup path part resolving by removing lots of duplicate code * Aligh HQL parsing expectations to the expected behavior of 5.x * Add method to `JavaType` that allows determining if a type is can be widened to another which is used for arithmetic type resolving * Implement validations for fetch owner checking * Fix issues with the id table creation due to lacking column lengths in the column DDL type * Fix issues and add some optimizations related to multi-table delete handling * Add the notion of a special "implicit" alias to avoid generating a unique alias for unaliased or implicit HQL joins * Properly implement multiple bag fetch validation * Make sure filter predicates are applied for all plural attribute joins * Fix some issues with undecidable parameter type inference * Fix some issues with negated SQM predicates not being converted to the proper SQL AST predicates * Fix issues with qualifying DML target referencing columns * Fix `is null` semantics for tuples referring to embeddable types * Capture necessary details from JdbcValuesMetadata in the cached data to avoid executing a query on cache hit when types should be inferred * Get rid of special CollectionPropertyNames and writeup a migration guide section for the replacements
2021-11-23 12:16:48 -05:00
=== Remove support for special plural attribute properties
Prior to 6.0, it was possible to de-reference special properties on plural attributes like `size` which was dropped.
The special properties lead to confusion and were sometimes ambiguous. The replacement is the function syntax.
size::
The collection size can be determined by using the `size( pluralAttribute )` function instead
elements::
The collection elements can be referred to by using the `value( pluralAttribute )` function instead
indices::
The collection indices can be referred to by using the `index( pluralAttribute )` or `key( pluralAttribute )` function instead
index::
The collection index can be referred to by using the `index( pluralAttribute )` or `key( pluralAttribute )` function instead
maxindex::
The collection maximum index can be determined by using the `maxindex( pluralAttribute )` function instead
minindex::
The collection minimum index can be determined by using the `minindex( pluralAttribute )` function instead
maxelement::
The collection maximum element can be determined by using the `maxelement( pluralAttribute )` function instead
minelement::
The collection minimum element can be determined by using the `minelement( pluralAttribute )` function instead
=== Remove support for comparing association against FK value
Previously Hibernate did allow comparing an association with an FK value like `... where alias.association = 1`
or `... where alias.association = alias.association.id` or even `... where alias.association = :param` where `param`
is bound to an integer `1`. This was supported prior to Hibernate 6.0 if the foreign key for the association is an integer.
The right way to do this is de-referencing the association by the FK attribute `... where alias.association.id = 1`
which is guaranteed to not produce a join, or use an entity reference for `... where alias.association = :param`
where `param` is bound to `entityManager.getReference(EntityClass.class, 1)`.
2021-09-27 14:19:54 -04:00
=== Removals
2021-09-27 14:19:54 -04:00
* JMX integration
* JACC integration
* @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'
2021-11-24 10:25:23 -05:00
=== Fetch behaviour change
We changed the way we detect circularity, we do not follow anymore a deep first detection, so what happens is that in a model like
```
@Entity
class Node {
@ManyToOne
Node node1;
@ManyToOne
Node node2;
}
```
being all eager we are executing a query with 4 joins
```
FROM Node
JOIN Node.node1
JOIN Node.node1.node2
JOIN Node.node2
JOIN Node.node2.node1
```
whereas before we
```
FROM Node
JOIN Node.node1
JOIN Node.node1.node2
```
and issue a select for `Node.node2` if the FK of `Node.node2` is not null
```
FROM Node.node2
JOIN Node.node2.node1
JOIN Node.node2.node1.node2
```
In this simple example this is not such a big deal, but if we increase the number of eager fetched self-associations
to e.g. 3 like here:
```
@Entity
class Node {
@ManyToOne
Node node1;
@ManyToOne
Node node2;
@ManyToOne
Node node3;
}
```
this results in mind-blowing 15 joins
```
FROM Node
JOIN Node.node1
JOIN Node.node1.node2
JOIN Node.node1.node2.node3
JOIN Node.node1.node3
JOIN Node.node1.node3.node2
JOIN Node.node2
JOIN Node.node2.node1
JOIN Node.node2.node1.node3
JOIN Node.node2.node3
JOIN Node.node2.node3.node1
JOIN Node.node3
JOIN Node.node3.node1
JOIN Node.node3.node1.node2
JOIN Node.node3.node2
JOIN Node.node3.node2.node1
```
as you can see, this leads to a lot of joins very quickly, but the behavior of 5.x simply was not intuitive.
To avoid creating so many joins, and also in general, we recommend that you use lazy fetching i.e. `@ManyToOne(fetch = FetchType.LAZY)`
or `@OneToOne(fetch = FetchType.LAZY)` for most associations, but this is especially important if you have multiple self-referencing associations as you can see in the example.