= 6.0 Migration Guide :toc: This guide discusses migration from Hibernate ORM version 6.0. For migration from earlier versions, see any other pertinent migration guides as well. == Background == 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 === 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" === 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. === 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 postAndComments = entityManager.createNamedQuery("fn_person_and_phones" ).setParameter( 1, 1L ).getResultList(); ``` is going to throw an `IllegalArgumentException`. The migration code is ``` List postAndComments = entityManager.createStoredProcedureQuery( "fn_person_and_phones", "person_with_phones" ).setParameter( 1, 1L ).getResultList(); ``` === SQM * Functions * Multi-table bulk manipulation HQL/Criteria query handling === Removals * 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' === 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.