From b2a76f055b485eb90f6e12c5ff8d160070b4ac44 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 6 Dec 2016 15:06:04 +0100 Subject: [PATCH] DATACMNS-1019 - Assert Hibernate 5.2 compatibility. Improved our detection of Hibernate 5.2 in the query lookup for String based queries, general PersistenceProvider detection (due to changed interface hierarchies in Hibernate 5.2). Tweaked the setup for some integration tests to point to Hibernate 5.2 specific persistence units using the new location for the persistence provider implementation class. --- .../data/jpa/provider/HibernateUtils.java | 21 +++++++++++- .../jpa/provider/PersistenceProvider.java | 12 ++++--- .../PersistenceProviderUnitTests.java | 17 ++++++++++ .../cdi/EntityManagerFactoryProducer.java | 6 +++- ...odelEntityInformationIntegrationTests.java | 3 +- src/test/resources/META-INF/persistence.xml | 34 ++++++++++++++++++- 6 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java b/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java index 84ce421b7..39f8e0258 100644 --- a/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java +++ b/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java @@ -37,21 +37,35 @@ public abstract class HibernateUtils { "org.hibernate.ejb.HibernateQuery"); private static final Method GET_HIBERNATE_QUERY; + private static final Class HIBERNATE_QUERY_INTERFACE; + private static final Method QUERY_STRING_METHOD; + private HibernateUtils() {} static { Class type = null; Method method = null; + ClassLoader classLoader = HibernateUtils.class.getClassLoader(); for (String typeName : TYPES) { try { - type = ClassUtils.forName(typeName, HibernateUtils.class.getClassLoader()); + type = ClassUtils.forName(typeName, classLoader); method = type.getMethod("getHibernateQuery"); } catch (Exception o_O) {} } GET_HIBERNATE_QUERY = method; + + Class queryInterface = null; + + try { + queryInterface = ClassUtils.forName("org.hibernate.query.Query", classLoader); + } catch (Exception o_O) {} + + HIBERNATE_QUERY_INTERFACE = queryInterface; + QUERY_STRING_METHOD = HIBERNATE_QUERY_INTERFACE == null ? null + : ReflectionUtils.findMethod(HIBERNATE_QUERY_INTERFACE, "getQueryString"); } /** @@ -61,6 +75,11 @@ public abstract class HibernateUtils { * @return */ public static String getHibernateQuery(Object query) { + + if (HIBERNATE_QUERY_INTERFACE != null && HIBERNATE_QUERY_INTERFACE.isInstance(query)) { + return String.class.cast(ReflectionUtils.invokeMethod(QUERY_STRING_METHOD, query)); + } + return ((Query) ReflectionUtils.invokeMethod(GET_HIBERNATE_QUERY, query)).getQueryString(); } } diff --git a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java index ac181bbf4..01517f0fc 100644 --- a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java +++ b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java @@ -54,7 +54,7 @@ import org.springframework.util.ReflectionUtils; * @author Oliver Gierke * @author Thomas Darimont */ -public enum PersistenceProvider implements QueryExtractor,ProxyIdAccessor { +public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor { /** * Hibernate persistence provider. @@ -65,8 +65,9 @@ public enum PersistenceProvider implements QueryExtractor,ProxyIdAccessor { * @see DATAJPA-444 */ HIBERNATE(// - Arrays.asList(HIBERNATE43_ENTITY_MANAGER_INTERFACE, HIBERNATE_ENTITY_MANAGER_INTERFACE), // - Arrays.asList(HIBERNATE43_JPA_METAMODEL_TYPE, HIBERNATE_JPA_METAMODEL_TYPE)) { + Arrays.asList(HIBERNATE52_ENTITY_MANAGER_INTERFACE, HIBERNATE43_ENTITY_MANAGER_INTERFACE, + HIBERNATE_ENTITY_MANAGER_INTERFACE), // + Arrays.asList(HIBERNATE52_JPA_METAMODEL_TYPE, HIBERNATE43_JPA_METAMODEL_TYPE, HIBERNATE_JPA_METAMODEL_TYPE)) { public String extractQueryString(Query query) { return HibernateUtils.getHibernateQuery(query); @@ -124,8 +125,7 @@ public enum PersistenceProvider implements QueryExtractor,ProxyIdAccessor { /** * EclipseLink persistence provider. */ - ECLIPSELINK(Collections.singleton(ECLIPSELINK_ENTITY_MANAGER_INTERFACE), - Collections.singleton(ECLIPSELINK_JPA_METAMODEL_TYPE)) { + ECLIPSELINK(Collections.singleton(ECLIPSELINK_ENTITY_MANAGER_INTERFACE), Collections.singleton(ECLIPSELINK_JPA_METAMODEL_TYPE)) { public String extractQueryString(Query query) { return ((JpaQuery) query).getDatabaseQuery().getJPQLString(); @@ -263,9 +263,11 @@ public enum PersistenceProvider implements QueryExtractor,ProxyIdAccessor { String ECLIPSELINK_ENTITY_MANAGER_INTERFACE = "org.eclipse.persistence.jpa.JpaEntityManager"; String HIBERNATE_ENTITY_MANAGER_INTERFACE = "org.hibernate.ejb.HibernateEntityManager"; String HIBERNATE43_ENTITY_MANAGER_INTERFACE = "org.hibernate.jpa.HibernateEntityManager"; + String HIBERNATE52_ENTITY_MANAGER_INTERFACE = "org.hibernate.Session"; String HIBERNATE_JPA_METAMODEL_TYPE = "org.hibernate.ejb.metamodel.MetamodelImpl"; String HIBERNATE43_JPA_METAMODEL_TYPE = "org.hibernate.jpa.internal.metamodel.MetamodelImpl"; + String HIBERNATE52_JPA_METAMODEL_TYPE = "org.hibernate.metamodel.internal.MetamodelImpl"; String ECLIPSELINK_JPA_METAMODEL_TYPE = "org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl"; String OPENJPA_JPA_METAMODEL_TYPE = "org.apache.openjpa.persistence.meta.MetamodelImpl"; } diff --git a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java index fa2327560..9f6c84d68 100644 --- a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java @@ -25,6 +25,8 @@ import java.util.List; import javax.persistence.EntityManager; +import org.hibernate.Version; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -102,6 +104,21 @@ public class PersistenceProviderUnitTests { assertThat(fromEntityManager(em), is(GENERIC_JPA)); } + /** + * @see DATAJPA-1019 + */ + @Test + public void detectsHibernatePersistenceProviderForHibernateVersion52() throws Exception { + + Assume.assumeThat(Version.getVersionString(), startsWith("5.2")); + + shadowingClassLoader.excludePackage("org.hibernate"); + + EntityManager em = mockProviderSpecificEntityManagerInterface(HIBERNATE52_ENTITY_MANAGER_INTERFACE); + + assertThat(fromEntityManager(em), is(HIBERNATE)); + } + private EntityManager mockProviderSpecificEntityManagerInterface(String interfaceName) throws ClassNotFoundException { Class providerSpecificEntityManagerInterface = InterfaceGenerator.generate(interfaceName, shadowingClassLoader, diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/EntityManagerFactoryProducer.java b/src/test/java/org/springframework/data/jpa/repository/cdi/EntityManagerFactoryProducer.java index 73e91fa53..d7cfd7811 100644 --- a/src/test/java/org/springframework/data/jpa/repository/cdi/EntityManagerFactoryProducer.java +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/EntityManagerFactoryProducer.java @@ -21,12 +21,16 @@ import javax.enterprise.inject.Produces; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; +import org.hibernate.Version; + class EntityManagerFactoryProducer { @Produces @ApplicationScoped public EntityManagerFactory createEntityManagerFactory() { - return Persistence.createEntityManagerFactory("cdi"); + + String hibernateVersion = Version.getVersionString(); + return Persistence.createEntityManagerFactory(hibernateVersion.startsWith("5.2") ? "cdi-52" : "cdi"); } public void close(@Disposes EntityManagerFactory entityManagerFactory) { diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java index c83fdbaff..a4ba76ad0 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java @@ -35,6 +35,7 @@ import javax.persistence.Persistence; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.Metamodel; +import org.hibernate.Version; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -333,7 +334,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { } protected String getMetadadataPersitenceUnitName() { - return "metadata"; + return Version.getVersionString().startsWith("5.2") ? "metadata-52" : "metadata"; } @SuppressWarnings("serial") diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index ea0e22431..5c24cbe85 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -71,7 +71,26 @@ - + + + org.hibernate.jpa.HibernatePersistenceProvider + org.springframework.data.jpa.domain.sample.MailMessage + org.springframework.data.jpa.domain.sample.MailSender + org.springframework.data.jpa.domain.sample.MailUser + org.springframework.data.jpa.domain.sample.User + org.springframework.data.jpa.repository.cdi.Person + org.springframework.data.jpa.domain.sample.Dummy + true + + + + + + + + + + org.springframework.data.jpa.domain.sample.User @@ -99,6 +118,19 @@ + + org.hibernate.jpa.HibernatePersistenceProvider + org.springframework.data.jpa.domain.sample.CustomAbstractPersistable + org.springframework.data.jpa.domain.sample.MailMessage + org.springframework.data.jpa.domain.sample.MailSender + org.springframework.data.jpa.domain.sample.MailUser + org.springframework.data.jpa.domain.sample.User + org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample + true + + + + org.eclipse.persistence.jpa.PersistenceProvider org.springframework.data.jpa.domain.sample.CustomAbstractPersistable