Align HibernateJpaVendorAdapter with Hibernate ORM 6.2
Includes documentation and test revisions. Closes gh-30288
This commit is contained in:
parent
3b364c2a3d
commit
4c8f1910c8
|
|
@ -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]]
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"/>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue