hibernate-orm/migration-guide.adoc

234 lines
12 KiB
Plaintext

= 5.2 Migration Guide
:toc:
This guide discusses migration from Hibernate ORM version 5.1 to version 5.2. For migration from
earlier versions, see any other pertinent migration guides as well.
== Background
Lots of work has been done for 6.0. One of the things 6.0 will need is a unified view of "type systems"
including its own type system (`Type`, `EntityPersister`, `CollectionPersister`, etc) and JPA's type system - which
would mean unifying all of this in hibernate-core. Because of this and the other large changes slated for 6.0
we decided to release a 5.2 that showed a clear migration path to the changes in 6.0 but that still supported the
older calls and expectations as much as possible.
== Move to Java 8 for baseline
Hibernate 5.2 is built using Java 8 JDK and will require Java 8 JRE at runtime (we are investigating whether
Java 9 will also work). This has a number of implications:
* The hibernate-java8 module has been merged into hibernate-core and the Java 8 date/time types are now natively
supported.
* (todo) support for Java 8 Optional
* (todo) support for other Java 8 features?
== hibernate-entitymanager merged into hibernate-core
The hibernate-entitymanager module has also been merged into hibernate-core.
* `org.hibernate.SessionFactory` now extends `javax.persistence.EntityManagerFactory` - temporarily it
technically extends `org.hibernate.jpa.HibernateEntityManagerFactory` (which in turn extends
`javax.persistence.EntityManagerFactory`) for backwards compatibility. `HibernateEntityManagerFactory`
is deprecated.
* `org.hibernate.Session` now extends `javax.persistence.EntityManager` - temporarily it
technically extends `org.hibernate.jpa.HibernateEntityManager` (which in turn extends
`javax.persistence.EntityManager`) for backwards compatibility. `HibernateEntityManager` is deprecated.
* `org.hibernate.Query` (deprecated in favor of new `org.hibernate.query.Query`) now extends the JPA contracts
`javax.persistence.Query` and `javax.persistence.TypedQuery`. `ProcedureCall` and `StoredProcedureQuery` as well.
* `org.hibernate.HibernateException` now extends `javax.persistence.PersistenceExceptions`. Hibernate methods
that "override" methods from their JPA counterparts now will also throw various JDK defined RuntimeExceptions
(such as `IllegalArgumentException`, `IllegalStateException`, etc) as required by the JPA contract.
* Persister/type access is now exposed through `org.hibernate.Metamodel`, which extends
`javax.persistence.metamodel.Metamodel`. MetamodelImpl now manages all aspects of type system (see below).
* Cache management has also been consolidated. `org.hibernate.Cache` now extends `javax.persistence.Cache`. CacheImpl
now manages all aspects of cache regions (see below).
== SessionFactory hierarchy cleanup
As part of merging hibernate-entitymanager into hibernate-core, I also wanted to take a moment to clean up
some of these very old contracts, In conjunction with the move to Java 8 (default methods) and needing to
implement JPA methods now in core I decided to implement more of a composition approach here, thus:
* SessionFactoryImplementor used to have a number of methods pertaining to managing and accessing entity and collection persisters.
Since we need to deal with JPA Metamodel contract anyway, I went ahead and moved all of that code into our new
`org.hibernate.metamodel.spi.MetamodelImplementor`
* SessionFactory and SessionFactoryImplementor each had a number of methods dealing with cache regions.
Many of these methods have been deprecated since 5.0 and those will be removed. However, the functionality
has been moved into the `org.hibernate.Cache` and `org.hibernate.engine.spi.CacheImplementor` contracts
helping implement JPA's `javax.persistence.Cache` role.
== Session and StatelessSession hierarchy cleanup
This one can affect implementors of certain extension contracts.
Specifically those previously accepting a `SessionImplementor` will likely now accept a `SharedSessionContract`.
== Persister and Tuplizer changes
Due to changes to SPIs for persisters (in `org.hibernate.persister` package) and tuplizers (in `org.hibernate.tuple`),
custom persisters and tuplizers will need to be updated to follow the new SPIs.
== LimitHandler changes
In Hibernate 4.3, dialect implementations that did not support a limit offset would fetch all rows for a query and
perform pagination in-memory. This solution, while functional, could have severe performance penalties. In 5.x,
we preferred to favor performance optimizations which meant dialect implementations would throw an exception if a
limit offset was specified but the dialect didn't support such syntax.
As of 5.2.5.Final, we have introduced a new setting, `hibernate.legacy_limit_handler`, that is designed to allow
users to enable the legacy 4.3 limit handler behavior. By default, this setting is _false_.
The specific dialects impacted by this change are restricted to the following.
* `Cache71Dialect`
* `DB2390Dialect`
* `InformixDialect`
* `IngresDialect`
* `RDMSOS2200Dialect`
* `SQLServerDialect`
* `TimesTenDialect`
NOTE: If a dialect that extends any in the above list but overrides the limit handler implementation, then those
dialects remain unchanged, e.g. `SQLServer2005Dialect`.
== Changes to schema management tooling
In 5.2.3, a new strategy for retrieving database tables was introduced that improves SchemaMigrator and SchemaValidator
performance. This strategy executes a single `java.sql.DatabaseMetaData#getTables(String, String, String, String[])`
call to determine if each `javax.persistence.Entity` has a mapped database table.
This strategy is the default, and uses the property setting `hibernate.hbm2ddl.jdbc_metadata_extraction_strategy=grouped`.
This strategy may require `hibernate.default_schema` and/or `hibernate.default_catalog` to be provided.
To use the old strategy, which executes a `java.sql.DatabaseMetaData#getTables(String, String, String, String[])` call for
each javax.persistence.Entity, use the property setting `hibernate.hbm2ddl.jdbc_metadata_extraction_strategy=individually`.
== Changes to how Clob values are processed using PostgreSQL81Dialect and its subclasses
Up to and including 5.2.8, `Clob` values and values for `String`, `character[]`, and `Character[]` attributes that are
annotated with `@Lob` were:
* bound using `Clob` representations of the data (using `PreparedStatement#setClob` or `CallableStatement#setClob`);
* retrieved as `Clob` values (using `ResultSet#getClob` or `CallableStatement#getClob`), which were converted to the
appropriate Java type;
* stored as PostgreSQL Large Objects; i.e., an `OID` for the value is stored in a `text` column,
which refers to the actual data stored in a different (PostgreSQL-specific) table.
In 5.2.9 and 5.2.10, due to the fix for https://hibernate.atlassian.net/browse/HHH-11477[HHH-11477], `Clob` values and values for `String`, `character[]`, and `Character[]`
attributes that are annotated with `@Lob` were:
* bound using `String` representations of the data (using `PreparedStatement#setString` or `CallableStatement#setString`);
* retrieved as `String` values (using `ResultSet#getString` or `CallableStatement#getString`), which were converted
to the appropriate Java type;
* stored as variable-length character strings.
In 5.2.11, the fix for https://hibernate.atlassian.net/browse/HHH-11477[HHH-11477] was reverted
(https://hibernate.atlassian.net/browse/HHH-11614[HHH-11614]) to restore the 5.2.8 behavior.
As a consequence of these changes, data persisted using a version of Hibernate prior to 5.2.9 cannot be read
using 5.2.9 or 5.2.10. Data persisted using Hibernate 5.2.9 or 5.2.10 can no longer be read using 5.2.11 or later.
A workaround that can be used in 5.2.9 and 5.2.10 that will restore the 5.2.8/5.2.11 behavior is to override the
PostgreSQL dialect with:
[source,java]
----
public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
if( sqlCode == Types.CLOB ){
return ClobTypeDescriptor.CLOB_BINDING;
}
return super.getSqlTypeDescriptorOverride( sqlCode );
}
----
In addition, any `Clob` values and values for `String`, `character[]`, `Character[]` attributes that are annotated with
`@Lob` that were stored as variable-length character strings using 5.2.9 or 5.2.10 should be updated to store the values
as PostgreSQL Large Objects before migrating to 5.2.11.
For example, if variable-length character strings were stored by 5.2.9 or 5.2.10 for the following mapping:
[source,java]
----
@Entity(name = "TestEntity")
@Table(name = "TEST_ENTITY")
public static class TestEntity {
@Id
@GeneratedValue
private long id;
@Lob
String firstLobField;
@Lob
String secondLobField;
@Lob
Clob clobField;
...
}
----
the variable-length character strings can be converted to PostgreSQL Large Objects by executing the following SQL:
[source,sql]
----
update test_entity
set clobfield = lo_from_bytea( 0, cast( clobfield as bytea ) ),
firstlobfield = lo_from_bytea( 0, cast( firstlobfield as bytea ) ),
secondlobfield = lo_from_bytea( 0, cast( secondlobfield as bytea ) )
----
=== Change in the `@TableGenerator` and `@SequenceGenerator` name scope
[IMPORTANT]
From 5.2.13 the id generator name scope was considered global but realizing this change may cause troubles for few existing projects (https://hibernate.atlassian.net/browse/HHH-12454[HHH-12454]), starting *from 5.2.17* the scope of the id generators names
will be considered local by default (which is the pre-5.2.13 behavior) and a new configuration setting `hibernate.jpa.compliance.global_id_generators`
can be used to enable the JPA compliant global scoping.
== Other changes
=== 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.2.18, 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.2.18 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.2.18, if an association is mapped with `FetchType.LAZY`, the assocation will
be lazily fetched, as expected.
See details on the https://hibernate.atlassian.net/browse/HHH-12687[HHH-12687] Jira issue.
== Misc
* `QueryCacheFactory` contract changed
* `RegionFactory` contract changes
* todo : merge `AvailableSettings` together
* `org.hibernate.Transaction` now extends JPA's `EntityTransaction` and follows its pre- and post- assertions.
e.g. `begin()` now throws an exception if transaction is already active.
* (todo) following the above one, JPA also says that only `PersistenceUnitTransactionType#JTA` EntityManagers
are allowed to access ``EntityTransaction``s. Need a strategy to handle this
* Hibernate now conforms with the JPA specification to not allow flushing updates outside of a transaction
boundary. To restore 5.1 behavior, allowing flush operations outside of a transaction boundary,
set `hibernate.allow_update_outside_transaction=true`.
* `Session#getFlushMode()` and `Query#getFlushMode()` clash in terms of Hibernate (`FlushMode`) and JPA (`FlushModeType`)
returns. `#getFlushMode()` has been altered to return JPA's `FlushModeType`. The Hibernate `FlushMode`
is still available via `#getHibernateFlushMode()` and `#setHibernateFlushMode()`. Same for `Session#getFlushMode()`
and `EntityManager#getFlushMode()`.
* Setting `hibernate.listeners.envers.autoRegister` has been deprecated in favor of
`hibernate.envers.autoRegisterListeners`.
* `AuditReader#getCurrentRevision()` has been deprecated in favor of `org.hibernate.envers.RevisionListener`.
* As of 5.2.11, `NoopOptimizer#generate()` will no longer skip negative values and 0 when it has a positive increment size; instead it will return the value obtained from the database.