diff --git a/pom.xml b/pom.xml index b6ba4ad4e..1b17b1c46 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 2.6.2 3.6.10.Final + hibernate-entitymanager 1.8.0.10 2.0.0 2.4.1 @@ -111,6 +112,13 @@ + + hibernate-52 + + 5.2.0.Final + hibernate-core + + eclipselink-next @@ -250,7 +258,7 @@ org.hibernate - hibernate-entitymanager + ${hibernate.artifact} ${hibernate} true diff --git a/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java b/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java new file mode 100644 index 000000000..84ce421b7 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/provider/HibernateUtils.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.provider; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.Query; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +/** + * Utility functions to work with Hibernate. Mostly using reflection to make sure common functionality can be executed + * against all the Hibernate version we support. + * + * @since 1.10.2 + * @soundtrack Benny Greb - Soulfood (Live, https://www.youtube.com/watch?v=9_ErMa_CtSw) + */ +@SuppressWarnings({ "deprecation", "rawtypes" }) +public abstract class HibernateUtils { + + private static final List TYPES = Arrays.asList("org.hibernate.jpa.HibernateQuery", + "org.hibernate.ejb.HibernateQuery"); + private static final Method GET_HIBERNATE_QUERY; + + private HibernateUtils() {} + + static { + + Class type = null; + Method method = null; + + for (String typeName : TYPES) { + try { + type = ClassUtils.forName(typeName, HibernateUtils.class.getClassLoader()); + method = type.getMethod("getHibernateQuery"); + } catch (Exception o_O) {} + } + + GET_HIBERNATE_QUERY = method; + } + + /** + * Return the query string of the underlying native Hibernate query. + * + * @param query + * @return + */ + public static String getHibernateQuery(Object 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 777011cb4..1c9eb844b 100644 --- a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java +++ b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java @@ -39,7 +39,6 @@ import org.eclipse.persistence.jpa.JpaQuery; import org.eclipse.persistence.queries.ScrollableCursor; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; -import org.hibernate.ejb.HibernateQuery; import org.hibernate.proxy.HibernateProxy; import org.springframework.data.util.CloseableIterator; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -67,7 +66,7 @@ public enum PersistenceProvider implements QueryExtractor,ProxyIdAccessor { Arrays.asList(HIBERNATE43_JPA_METAMODEL_TYPE, HIBERNATE_JPA_METAMODEL_TYPE)) { public String extractQueryString(Query query) { - return ((HibernateQuery) query).getHibernateQuery().getQueryString(); + return HibernateUtils.getHibernateQuery(query); } /** diff --git a/src/test/java/org/springframework/data/jpa/infrastructure/HibernateTestUtils.java b/src/test/java/org/springframework/data/jpa/infrastructure/HibernateTestUtils.java new file mode 100644 index 000000000..34329c932 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/infrastructure/HibernateTestUtils.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.infrastructure; + +import java.util.Arrays; +import java.util.List; + +import javax.persistence.spi.PersistenceProvider; + +import org.springframework.util.ClassUtils; + +/** + * Testing utilities for Hibernate. + * + * @author Oliver Gierke + * @soundtrack Ron Spielman - Africa's Napoleon (Swimming In The Dark) + * @since 1.10.2 + */ +public class HibernateTestUtils { + + private static final List PROVIDER_TYPES = Arrays.asList("org.hibernate.jpa.HibernatePersistenceProvider", + "org.hibernate.ejb.HibernatePersistence"); + + /** + * Returns the Hibernate {@link PersistenceProvider}. + * + * @return + */ + public static PersistenceProvider getPersistenceProvider() { + + ClassLoader classLoader = HibernateTestUtils.class.getClassLoader(); + + for (String provider : PROVIDER_TYPES) { + + if (ClassUtils.isPresent(provider, classLoader)) { + + try { + return (PersistenceProvider) ClassUtils.forName(provider, classLoader).newInstance(); + } catch (Exception o_O) { + throw new RuntimeException(o_O); + } + } + } + + throw new IllegalStateException("Could not obtain Hibernate PersistenceProvider!"); + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java index 5e3e2e09c..7f34b6b4d 100644 --- a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015 the original author or authors. + * Copyright 2011-2016 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. @@ -29,7 +29,6 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; -import org.hibernate.ejb.HibernateEntityManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -117,7 +116,7 @@ public class CrudMethodMetadataUnitTests { @Test public void appliesLockModeAndQueryHintsToQuerydslQuery() { - when(em.getDelegate()).thenReturn(mock(HibernateEntityManager.class)); + when(em.getDelegate()).thenReturn(mock(EntityManager.class)); when(em.createQuery(anyString())).thenReturn(query); repository.findOne(QRole.role.name.eq("role")); diff --git a/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java index 4bec37c30..0ea336ef3 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java @@ -33,17 +33,16 @@ import javax.persistence.Query; import javax.persistence.TemporalType; import org.hibernate.Version; -import org.hibernate.ejb.HibernateQuery; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; -import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.HibernateUtils; import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.jpa.repository.Temporal; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; @@ -114,22 +113,21 @@ public class PartTreeJpaQueryIntegrationTests { Query query = jpaQuery.createQuery(new Object[] { "Matthews", new PageRequest(0, 1) }); - HibernateQuery hibernateQuery = getValue(query, PROPERTY); - assertThat(hibernateQuery.getHibernateQuery().getQueryString(), endsWith("firstname=:param0")); + assertThat(HibernateUtils.getHibernateQuery(getValue(query, PROPERTY)), endsWith("firstname=:param0")); query = jpaQuery.createQuery(new Object[] { null, new PageRequest(0, 1) }); - hibernateQuery = getValue(query, PROPERTY); - assertThat(hibernateQuery.getHibernateQuery().getQueryString(), endsWith("firstname is null")); + assertThat(HibernateUtils.getHibernateQuery(getValue(query, PROPERTY)), endsWith("firstname is null")); } private void testIgnoreCase(String methodName, Object... values) throws Exception { Class[] parameterTypes = new Class[values.length]; + for (int i = 0; i < values.length; i++) { parameterTypes[i] = values[i].getClass(); } - Method method = UserRepository.class.getMethod(methodName, parameterTypes); + JpaQueryMethod queryMethod = getQueryMethod(methodName, parameterTypes); PartTreeJpaQuery jpaQuery = new PartTreeJpaQuery(queryMethod, entityManager, PersistenceProvider.fromEntityManager(entityManager)); diff --git a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java index 8a87e6274..d62543c92 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/QueryUtilsIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2016 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. @@ -39,13 +39,13 @@ import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceProviderResolver; import javax.persistence.spi.PersistenceProviderResolverHolder; -import org.hibernate.ejb.HibernatePersistence; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.data.jpa.domain.sample.Category; import org.springframework.data.jpa.domain.sample.Order; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.infrastructure.HibernateTestUtils; import org.springframework.data.mapping.PropertyPath; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -191,16 +191,16 @@ public class QueryUtilsIntegrationTests { } /** - * A {@link PersistenceProviderResolver} that returns only {@link HibernatePersistence} and ignores other - * {@link PersistenceProvider}s. + * A {@link PersistenceProviderResolver} that returns only a Hibernate {@link PersistenceProvider} and ignores others. * * @author Thomas Darimont + * @author Oliver Gierke */ static class HibernateOnlyPersistenceProviderResolver implements PersistenceProviderResolver { @Override public List getPersistenceProviders() { - return Arrays. asList(new HibernatePersistence()); + return Arrays.asList(HibernateTestUtils.getPersistenceProvider()); } @Override diff --git a/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java index 8098145bd..e5b9eb1e4 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaContextIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 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. @@ -24,7 +24,6 @@ import java.util.HashSet; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; -import org.hibernate.ejb.HibernatePersistence; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; @@ -40,6 +39,7 @@ import org.springframework.context.annotation.FilterType; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.jpa.domain.sample.Category; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.infrastructure.HibernateTestUtils; import org.springframework.data.jpa.repository.JpaContext; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; @@ -147,7 +147,7 @@ public class DefaultJpaContextIntegrationTests { String persistenceUnitName) { LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); - factoryBean.setPersistenceProvider(new HibernatePersistence()); + factoryBean.setPersistenceProvider(HibernateTestUtils.getPersistenceProvider()); factoryBean.setDataSource(new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build()); factoryBean.setPersistenceUnitName(persistenceUnitName);