Align HibernateJpaVendorAdapter with Hibernate ORM 6.2

Includes documentation and test revisions.

Closes gh-30288
This commit is contained in:
Juergen Hoeller 2023-05-23 20:33:19 +02:00
parent 3b364c2a3d
commit 4c8f1910c8
7 changed files with 58 additions and 43 deletions

View File

@ -8,10 +8,16 @@ implementations and transaction demarcation. Most of these patterns can be direc
translated to all other supported ORM tools. The later sections in this chapter then translated to all other supported ORM tools. The later sections in this chapter then
cover the other ORM technologies and show brief examples. cover the other ORM technologies and show brief examples.
NOTE: As of Spring Framework 5.3, Spring requires Hibernate ORM 5.2+ for Spring's [NOTE]
====
As of Spring Framework 6.0, Spring requires Hibernate ORM 5.5+ for Spring's
`HibernateJpaVendorAdapter` as well as for a native Hibernate `SessionFactory` setup. `HibernateJpaVendorAdapter` as well as for a native Hibernate `SessionFactory` setup.
It is strongly recommended to go with Hibernate ORM 5.4 for a newly started application. We recommend Hibernate ORM 5.6 as the last feature branch in that Hibernate generation.
For use with `HibernateJpaVendorAdapter`, Hibernate Search needs to be upgraded to 5.11.6.
Hibernate ORM 6.x is only supported as a JPA provider (`HibernateJpaVendorAdapter`).
Plain `SessionFactory` setup with the `orm.hibernate5` package is not supported anymore.
We recommend Hibernate ORM 6.1/6.2 with JPA-style setup for new development projects.
====
[[orm-session-factory-setup]] [[orm-session-factory-setup]]

View File

@ -74,7 +74,7 @@ import org.springframework.util.ReflectionUtils;
/** /**
* {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate. * {@link org.springframework.orm.jpa.JpaDialect} implementation for Hibernate.
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1. * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Costin Leau * @author Costin Leau

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect; import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.DerbyTenSevenDialect; import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HANAColumnStoreDialect; import org.hibernate.dialect.HANAColumnStoreDialect;
@ -36,15 +37,17 @@ import org.hibernate.dialect.Informix10Dialect;
import org.hibernate.dialect.MySQL57Dialect; import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.PostgreSQL95Dialect; import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServer2012Dialect; import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/** /**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate. * {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
* Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1. * Compatible with Hibernate ORM 5.5/5.6 as well as 6.0/6.1/6.2.
* *
* <p>Exposes Hibernate's persistence provider and Hibernate's Session as extended * <p>Exposes Hibernate's persistence provider and Hibernate's Session as extended
* EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common * EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common
@ -69,6 +72,9 @@ import org.springframework.lang.Nullable;
*/ */
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
private static final boolean oldDialectsPresent = ClassUtils.isPresent(
"org.hibernate.dialect.PostgreSQL95Dialect", HibernateJpaVendorAdapter.class.getClassLoader());
private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect(); private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect();
private final PersistenceProvider persistenceProvider; private final PersistenceProvider persistenceProvider;
@ -167,22 +173,40 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
* @param database the target database * @param database the target database
* @return the Hibernate database dialect class, or {@code null} if none found * @return the Hibernate database dialect class, or {@code null} if none found
*/ */
@SuppressWarnings("deprecation") // for Derby/PostgreSQLDialect on Hibernate 6.2
@Nullable @Nullable
protected Class<?> determineDatabaseDialectClass(Database database) { protected Class<?> determineDatabaseDialectClass(Database database) {
return switch (database) { if (oldDialectsPresent) { // Hibernate <6.2
case DB2 -> DB2Dialect.class; return switch (database) {
case DERBY -> DerbyTenSevenDialect.class; case DB2 -> DB2Dialect.class;
case H2 -> H2Dialect.class; case DERBY -> DerbyTenSevenDialect.class;
case HANA -> HANAColumnStoreDialect.class; case H2 -> H2Dialect.class;
case HSQL -> HSQLDialect.class; case HANA -> HANAColumnStoreDialect.class;
case INFORMIX -> Informix10Dialect.class; case HSQL -> HSQLDialect.class;
case MYSQL -> MySQL57Dialect.class; case INFORMIX -> Informix10Dialect.class;
case ORACLE -> Oracle12cDialect.class; case MYSQL -> MySQL57Dialect.class;
case POSTGRESQL -> PostgreSQL95Dialect.class; case ORACLE -> Oracle12cDialect.class;
case SQL_SERVER -> SQLServer2012Dialect.class; case POSTGRESQL -> PostgreSQL95Dialect.class;
case SYBASE -> SybaseDialect.class; case SQL_SERVER -> SQLServer2012Dialect.class;
default -> null; case SYBASE -> SybaseDialect.class;
}; default -> null;
};
}
else { // Hibernate 6.2 aligned
return switch (database) {
case DB2 -> DB2Dialect.class;
case DERBY -> DerbyDialect.class;
case H2 -> H2Dialect.class;
case HANA -> HANAColumnStoreDialect.class;
case HSQL -> HSQLDialect.class;
case MYSQL -> MySQL57Dialect.class;
case ORACLE -> Oracle12cDialect.class;
case POSTGRESQL -> PostgreSQLDialect.class;
case SQL_SERVER -> SQLServer2012Dialect.class;
case SYBASE -> SybaseDialect.class;
default -> null;
};
}
} }
@Override @Override

View File

@ -43,6 +43,7 @@ import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
* @since 4.1 * @since 4.1
* @see Configuration#addPackage * @see Configuration#addPackage
*/ */
@SuppressWarnings("removal") // for Environment properties on Hibernate 6.2
class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider { class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider {
static { static {
@ -53,7 +54,7 @@ class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider
} }
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings({"rawtypes", "unchecked"}) // on Hibernate 6
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) { public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
final List<String> mergedClassesAndPackages = new ArrayList<>(info.getManagedClassNames()); final List<String> mergedClassesAndPackages = new ArrayList<>(info.getManagedClassNames());
if (info instanceof SmartPersistenceUnitInfo smartInfo) { if (info instanceof SmartPersistenceUnitInfo smartInfo) {
@ -65,7 +66,6 @@ class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider
public List<String> getManagedClassNames() { public List<String> getManagedClassNames() {
return mergedClassesAndPackages; return mergedClassesAndPackages;
} }
@Override @Override
public void pushClassTransformer(EnhancementContext enhancementContext) { public void pushClassTransformer(EnhancementContext enhancementContext) {
if (!NativeDetector.inNativeImage()) { if (!NativeDetector.inNativeImage()) {

View File

@ -49,32 +49,19 @@ public class HibernateEntityManagerFactoryIntegrationTests extends AbstractConta
@Test @Test
public void testCanCastNativeEntityManagerFactoryToHibernateEntityManagerFactoryImpl() { public void testCanCastNativeEntityManagerFactoryToHibernateEntityManagerFactoryImpl() {
EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) entityManagerFactory; EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) entityManagerFactory;
boolean condition1 = emfi.getNativeEntityManagerFactory() instanceof org.hibernate.jpa.HibernateEntityManagerFactory; assertThat(emfi.getNativeEntityManagerFactory() instanceof SessionFactory).isTrue();
assertThat(condition1).isTrue();
// as of Hibernate 5.2
boolean condition = emfi.getNativeEntityManagerFactory() instanceof SessionFactory;
assertThat(condition).isTrue();
} }
@Test @Test
public void testCanCastSharedEntityManagerProxyToHibernateEntityManager() { public void testCanCastSharedEntityManagerProxyToHibernateEntityManager() {
boolean condition1 = sharedEntityManager instanceof org.hibernate.jpa.HibernateEntityManager; assertThat(((EntityManagerProxy) sharedEntityManager).getTargetEntityManager() instanceof Session).isTrue();
assertThat(condition1).isTrue();
// as of Hibernate 5.2
boolean condition = ((EntityManagerProxy) sharedEntityManager).getTargetEntityManager() instanceof Session;
assertThat(condition).isTrue();
} }
@Test @Test
public void testCanUnwrapAopProxy() { public void testCanUnwrapAopProxy() {
EntityManager em = entityManagerFactory.createEntityManager(); EntityManager em = entityManagerFactory.createEntityManager();
EntityManager proxy = ProxyFactory.getProxy(EntityManager.class, new SingletonTargetSource(em)); EntityManager proxy = ProxyFactory.getProxy(EntityManager.class, new SingletonTargetSource(em));
boolean condition = em instanceof org.hibernate.jpa.HibernateEntityManager; assertThat(proxy.unwrap(Session.class)).isSameAs(em);
assertThat(condition).isTrue();
boolean condition1 = proxy instanceof org.hibernate.jpa.HibernateEntityManager;
assertThat(condition1).isFalse();
assertThat(proxy.unwrap(org.hibernate.jpa.HibernateEntityManager.class)).isNotNull();
assertThat(proxy.unwrap(org.hibernate.jpa.HibernateEntityManager.class)).isSameAs(em);
assertThat(proxy.getDelegate()).isSameAs(em.getDelegate()); assertThat(proxy.getDelegate()).isSameAs(em.getDelegate());
} }

View File

@ -30,6 +30,7 @@ import jakarta.persistence.PersistenceContext;
import jakarta.persistence.PersistenceContextType; import jakarta.persistence.PersistenceContextType;
import jakarta.persistence.PersistenceProperty; import jakarta.persistence.PersistenceProperty;
import jakarta.persistence.PersistenceUnit; import jakarta.persistence.PersistenceUnit;
import org.hibernate.Session;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
@ -700,8 +701,7 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
public static class DefaultVendorSpecificPrivatePersistenceContextField { public static class DefaultVendorSpecificPrivatePersistenceContextField {
@PersistenceContext @PersistenceContext
@SuppressWarnings("deprecation") private Session em;
private org.hibernate.ejb.HibernateEntityManager em;
} }

View File

@ -28,9 +28,7 @@
<property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean> </bean>
<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory"/> <bean id="hibernateStatistics" factory-bean="entityManagerFactory" factory-method="getStatistics"/>
<bean id="hibernateStatistics" factory-bean="sessionFactory" factory-method="getStatistics"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>