Skip to content

Commit

Permalink
Align HibernateJpaVendorAdapter with Hibernate ORM 6.2
Browse files Browse the repository at this point in the history
Includes documentation and test revisions.

Closes gh-30288
  • Loading branch information
jhoeller committed May 23, 2023
1 parent 3b364c2 commit 4c8f191
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 43 deletions.
12 changes: 9 additions & 3 deletions framework-docs/modules/ROOT/pages/data-access/orm/hibernate.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

/**
* {@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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -28,6 +28,7 @@
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;
Expand All @@ -36,15 +37,17 @@
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
Expand All @@ -69,6 +72,9 @@
*/
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;
Expand Down Expand Up @@ -167,22 +173,40 @@ private Map<String, Object> buildJpaPropertyMap(boolean connectionReleaseOnClose
* @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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* @since 4.1
* @see Configuration#addPackage
*/
@SuppressWarnings("removal") // for Environment properties on Hibernate 6.2
class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider {

static {
Expand All @@ -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) {
Expand All @@ -65,7 +66,6 @@ public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitI
public List<String> getManagedClassNames() {
return mergedClassesAndPackages;
}

@Override
public void pushClassTransformer(EnhancementContext enhancementContext) {
if (!NativeDetector.inNativeImage()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,32 +49,19 @@ protected String[] getConfigLocations() {
@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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -700,8 +701,7 @@ public static class DefaultPrivatePersistenceContextField {
public static class DefaultVendorSpecificPrivatePersistenceContextField {

@PersistenceContext
@SuppressWarnings("deprecation")
private org.hibernate.ejb.HibernateEntityManager em;
private Session em;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"/>

Expand Down

0 comments on commit 4c8f191

Please sign in to comment.