Skip to content

Latest commit

 

History

History
212 lines (148 loc) · 11.5 KB

migration-guide.adoc

File metadata and controls

212 lines (148 loc) · 11.5 KB

5.3 Migration Guide

This guide discusses migration from Hibernate ORM version 5.2 to version 5.3. For migration from earlier versions, see any other pertinent migration guides as well.

Background

Hibernate 5.3 adds support for the JPA 2.2 specification

Known changes

Changes to positional query parameter handling

This really breaks down into 2 related changes:

  • Support for JDBC-style parameter declarations in HQL/JPQL queries has been removed. This feature has been deprecated since 4.1 and removing it made implementing the second change, so we decided to remove that support. JDBC-style parameter declaration is still supported in native-queries.

  • Since JPA positional parameters really behave more like named parameters (they can be repeated, declared in any order, etc.) Hibernate used to treat them as named parameters - it relied on Hibernate’s JPA wrapper to interpret the JPA setParameter calls and properly handle delegating to the named variant. This is actually a regression in 5.2 as it causes javax.persistence.Parameter#getPosition to report null.

For JDBC-style parameter declarations in native queries, we have also moved to using one-based instead of zero-based parameter binding to be consistent with JPA. That can temporarily be reverted by setting the hibernate.query.sql.jdbc_style_params_base setting to true which reverts to expecting zero-based binding.

Change in the @TableGenerator stored value

In order to be compliant with the JPA specification, the sequence value stored by Hibernate 5.3 in the database table used by the javax.persistence.TableGenerator is the last generated value. Previously, Hibernate stored the next sequence value.

For backward compatibility, a new setting called hibernate.id.generator.stored_last_used was introduced, which gives you the opportunity to fall back to the old Hibernate behavior.

Note

Existing applications migrating to 5.3 and using the @TableGenerator have to set the hibernate.id.generator.stored_last_used configuration property to false.

Query parameters

Method org.hibernate.type.Type getType() in org.hibernate.query.QueryParameter was renamed to getHibernateType().

This was done in order to allow for the re-introduction of Class<T> getType() in a sub-interface, org.hibernate.procedure.ParameterRegistration. That second method had been removed in 5.2, breaking compatibility with 5.1.

Second-level cache provider SPI changes

Hibernate’s second-level cache SPI needed to be redesigned to match with expectations between Hibernate and the various caching providers. And the SPI did not really clarify the intention. These mis-matched expectations certainly had the potential to lead to bugs. Although it was originally slated for 6.0 to delay the SPI changes, we decided to back-port the work to 5.3 to address a number of bugs that could have been avoided with a clarified SPI.

The changes also allow the caching providers to perform serious optimizations based on the users configuration of domain data caching in Hibernate.

Details can be seen on the HHH-11356 Jira issue

One potential upgrade concern is any custom org.hibernate.cache.spi.QueryCacheFactory implementations. org.hibernate.cache.spi.QueryCacheFactory was meant as a means to allow service providers the ability to define query result caching, generally with more stale-tolerant query result invalidation handling. However, the contract also bound it to the old second level cache contracts so they had to be updated. Its responsibilities also changed so we also decided to "rename it" to org.hibernate.cache.spi.TimestampsCacheFactory

Another specific change to be aware of is accessing cache entries via SecondLevelCacheStatistics#getEntries and NaturalIdCacheStatistics#getEntries. These methods have been deprecated, however the new caching SPI does not really require caching providers to support this. As of 5.3 these methods inherently return an empty Map (Collections#emptyMap). This has always been something that providers did not implement "correctly" anyway

Statistics changes

The change for HHH-11356 required changes in its consumers. One such consumer is the Hibernate Statistics system…​.

Native (non-JPA) Pagination changes

When hibernate-entitymanager module was merged into hibernate-core in Hibernate ORM 5.2, the contracts for the following pre-existing org.hibernate.Query methods were changed to be specified by JPA javax.persistence.Query methods: getFirstResult(), setFirstResult(int), getMaxResults(), and setMaxResults().

In 5.3.2, the following methods were temporarily added to org.hibernate.Query to make it easier to migrate native applications from Hibernate ORM 5.1 to 5.3, and maintain 5.1 pagination behavior:

  • setHibernateFirstResult(int) behaves the same as the 5.1 version of setFirstResult(), with a small difference — calling setHibernateFirstResult(int) with a negative value will result in getHibernateFirstResult() returning 0, instead of the negative value. Note that this behavior differs from JPA in that javax.persistence.Query.setFirstResult(int) throws IllegalArgumentException when called with a negative value.

  • getHibernateFirstResult() behaves the same as the 5.1 version of getFirstResult(), except for the difference mentioned above when setHibernateFirstResult(int) is called with a negative number. This method returns null if no value was set via setHibernateFirstResult(int) (or setFirstResult(int)). Note that this behavior differs from JPA in that javax.persistence.Query.getFirstResult() returns 0 when uninitialized.

  • setHibernateMaxResults behaves the same as the 5.1 version of setMaxResults(); setting a value less than or equal to 0 is considered uninitialized, resulting in no limit on the number of results. Note that this behavior differs from JPA javax.persistence.Query.setMaxResults(int), which, when called with a negative value, throws IllegalArgumentException, and when called with a value of 0, indicates that the query should return no results.

  • getHibernateMaxResults behaves the same as the 5.1 version of #getMaxResults. This method returns null if uninitialized or a value less than or equal to 0 was set via setHibernateMaxResults(int) (or setMaxResults(int)). Note that this behavior differs from JPA in that javax.persistence.Query.getMaxResults() returns `Integer.MAX_VALUE when uninitialized.

These methods are deprecated, and will be removed in a future version. To be portable with future Hibernate versions, applications should be changed to use the JPA methods.

Drop hibernate-infinispan module

Support for using Infinispan as a Hibernate 2nd-level cache provider has been moved to the Infinispan project so the hibernate-infinispan module has been dropped.

A relocation pom which is pointing to org.infinispan:infinispan-hibernate-cache dependency is still generated, therefore, avoiding the need of updating any library dependency.

The relocation pom may be dropped in a future release.

EnhancementTask changes

The API of the org.hibernate.tool.enhance.EnhancementTask Ant task was changed, specifically the #addFileset method was dropped in favor of #setBase and #setDir

See details on the HHH-11795 Jira issue.

The main gist is that EnhancementTask was fixed (through a contribution) to actually work with Enhancer from BytecodeProvider. Previously it had not. And part of fixing that required this change.

Many-to-one association in embeddable collection elements and composite IDs

A bug introduced in 4.3 caused many-to-one associations in embeddable collection elements and composite IDs to be eagerly fetched, even when explicitly mapped as lazy.

This bug does not affect many-to-one associations that are not in a composite ID or embeddable collection element.

In 5.3.2, this bug was fixed. As a result, such associations will be fetched as specified by their mappings.

Many-to-one associations mapped by using native HBM xml are lazy by default. In order to keep the associations eager in 5.3.2 and later, mappings will need to explicitly specify that they are non-lazy.

When mapped with annotations, many-to-one associations use FetchType.EAGER by default. Starting in 5.3.2, if an association is mapped with FetchType.LAZY, the assocation will be lazily fetched, as expected.

See details on the HHH-12687 Jira issue.

JpaIntegrator removed

JPA and native implementations of Hibernate event listeners were unified (see https://hibernate.atlassian.net/browse/HHH-11264) making the org.hibernate.jpa.event.spi.JpaIntegrator no longer needed.

Note

Existing applications migrating to 5.3 with classes extending org.hibernate.jpa.event.spi.JpaIntegrator have to change these classes to implement the org.hibernate.integrator.spi.Integrator interface.

Persister changes

Due to changes to SPIs for persisters (in org.hibernate.persister package), custom persisters will need to be updated to follow the new SPIs.

5.1 → 5.3 exception handling changes

In 5.3 (as well as 5.2), exception handling for a SessionFactory built via Hibernate’s native bootstrapping wraps or converts HibernateException according to the JPA specification unless the operation is Hibernate-specific (e.g., Session#save, Session#saveOrUpdate).

In 5.3.3, a property was added, hibernate.native_exception_handling_51_compliance, which indicates if exception handling for a SessionFactory built via Hibernate’s native bootstrapping should behave the same as native exception handling in Hibernate ORM 5.1. When set to true, HibernateException will not be wrapped or converted according to the JPA specification. This setting will be ignored for a SessionFactory built via JPA bootstrapping.

5.1 → 5.3 entity class "where" mapping changes

Starting in 5.2.0, when an entity class uses annotations to map a "where" clause (i.e., @Where(clause="…​")), that "where" clause is taken into account when loading one-to-many and many-to-many associations.

Starting in 5.3.5, the same functionality applies to an entity’s where clause mapped using hbm.xml (e.g., `<entity …​ where="…​"/>)

In 5.3.7, a new property was added, hibernate.use_entity_where_clause_for_collections, that provides control over whether the entity’s "where" clause is taken into account when loading one-to-many or many-to-many collections of that type of entity. The property is set to true by default. You can go back to the previous behavior (ignoring the entity’s mapped where clause) by setting hibernate.use_entity_where_clause_for_collections to false.

5.3 → 6.0 compatibility changes

The original driving force behind these series of changes is an effort to be as proactive as possible about designing compatibility between 5.3 and 6.0.

Type system changes

Use of NavigableRole, back-ported from 6.0 rather than plain String