Browse Source

Align HibernateJpaVendorAdapter with Hibernate ORM 6.2

Includes documentation and test revisions.

Closes gh-30288
pull/30619/head
Juergen Hoeller 1 year ago
parent
commit
4c8f1910c8
  1. 12
      framework-docs/modules/ROOT/pages/data-access/orm/hibernate.adoc
  2. 2
      spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java
  3. 56
      spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java
  4. 4
      spring-orm/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java
  5. 19
      spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java
  6. 4
      spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceInjectionTests.java
  7. 4
      spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml

12
framework-docs/modules/ROOT/pages/data-access/orm/hibernate.adoc

@ -8,10 +8,16 @@ implementations and transaction demarcation. Most of these patterns can be direc @@ -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
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.
It is strongly recommended to go with Hibernate ORM 5.4 for a newly started application.
For use with `HibernateJpaVendorAdapter`, Hibernate Search needs to be upgraded to 5.11.6.
We recommend Hibernate ORM 5.6 as the last feature branch in that Hibernate generation.
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]]

2
spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaDialect.java vendored

@ -74,7 +74,7 @@ import org.springframework.util.ReflectionUtils; @@ -74,7 +74,7 @@ import org.springframework.util.ReflectionUtils;
/**
* {@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 Costin Leau

56
spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java vendored

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.hibernate.Session; @@ -28,6 +28,7 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HANAColumnStoreDialect;
@ -36,15 +37,17 @@ import org.hibernate.dialect.Informix10Dialect; @@ -36,15 +37,17 @@ import org.hibernate.dialect.Informix10Dialect;
import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* {@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
* EntityManager interface, and adapts {@link AbstractJpaVendorAdapter}'s common
@ -69,6 +72,9 @@ import org.springframework.lang.Nullable; @@ -69,6 +72,9 @@ import org.springframework.lang.Nullable;
*/
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 PersistenceProvider persistenceProvider;
@ -167,22 +173,40 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { @@ -167,22 +173,40 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
* @param database the target database
* @return the Hibernate database dialect class, or {@code null} if none found
*/
@SuppressWarnings("deprecation") // for Derby/PostgreSQLDialect on Hibernate 6.2
@Nullable
protected Class<?> determineDatabaseDialectClass(Database database) {
return switch (database) {
case DB2 -> DB2Dialect.class;
case DERBY -> DerbyTenSevenDialect.class;
case H2 -> H2Dialect.class;
case HANA -> HANAColumnStoreDialect.class;
case HSQL -> HSQLDialect.class;
case INFORMIX -> Informix10Dialect.class;
case MYSQL -> MySQL57Dialect.class;
case ORACLE -> Oracle12cDialect.class;
case POSTGRESQL -> PostgreSQL95Dialect.class;
case SQL_SERVER -> SQLServer2012Dialect.class;
case SYBASE -> SybaseDialect.class;
default -> null;
};
if (oldDialectsPresent) { // Hibernate <6.2
return switch (database) {
case DB2 -> DB2Dialect.class;
case DERBY -> DerbyTenSevenDialect.class;
case H2 -> H2Dialect.class;
case HANA -> HANAColumnStoreDialect.class;
case HSQL -> HSQLDialect.class;
case INFORMIX -> Informix10Dialect.class;
case MYSQL -> MySQL57Dialect.class;
case ORACLE -> Oracle12cDialect.class;
case POSTGRESQL -> PostgreSQL95Dialect.class;
case SQL_SERVER -> SQLServer2012Dialect.class;
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

4
spring-orm/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java vendored

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

19
spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java

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

4
spring-orm/src/test/java/org/springframework/orm/jpa/support/PersistenceInjectionTests.java

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

4
spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml

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

Loading…
Cancel
Save