From a0ba2cfc632aaef3bf2936c90f210843962d61b3 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 31 Jul 2018 08:09:16 +0200 Subject: [PATCH] DATAJPA-1379 - Fixed detection of PersistenceProvider when EntityManager is a proxy. We now use the delegate to test the applicability of the PersistenceProvider not just for determining the and the key cash. This fixes the issue because the underlying issue was that the generic PersistenceProvider was used. Which return false for `canExtractQuery` which prevented the constructor call in the query to be detected. Original pull request: #287. --- .../data/jpa/provider/JpaClassUtils.java | 6 +++++- .../jpa/provider/PersistenceProvider.java | 3 ++- .../PersistenceProviderUnitTests.java | 19 ++++++++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java b/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java index 7b2ac83ce..54e023b4c 100644 --- a/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java +++ b/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java @@ -43,7 +43,11 @@ abstract class JpaClassUtils { * @return */ public static boolean isEntityManagerOfType(EntityManager em, String type) { - return isOfType(em, type, em.getDelegate().getClass().getClassLoader()); + Object delegate = em.getDelegate(); + if (delegate instanceof EntityManager) { + em = (EntityManager) delegate; + } + return isOfType(em, type, delegate.getClass().getClassLoader()); } public static boolean isMetamodelOfType(Metamodel metamodel, String type) { 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 ee4f6d19a..9bb7f00e3 100644 --- a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java +++ b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java @@ -44,6 +44,7 @@ import org.springframework.util.ConcurrentReferenceHashMap; * @author Oliver Gierke * @author Thomas Darimont * @author Mark Paluch + * @author Jens Schauder */ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor { @@ -224,7 +225,7 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor { String OPENJPA_JPA_METAMODEL_TYPE = "org.apache.openjpa.persistence.meta.MetamodelImpl"; } - private static ConcurrentReferenceHashMap, PersistenceProvider> CACHE = new ConcurrentReferenceHashMap, PersistenceProvider>(); + static ConcurrentReferenceHashMap, PersistenceProvider> CACHE = new ConcurrentReferenceHashMap, PersistenceProvider>(); private final Iterable entityManagerClassNames; private final Iterable metamodelClassNames; 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 78fcdfb58..62b4419f9 100644 --- a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java @@ -40,6 +40,7 @@ import org.springframework.util.ClassUtils; * * @author Thomas Darimont * @author Oliver Gierke + * @author Jens Schauder */ public class PersistenceProviderUnitTests { @@ -47,6 +48,9 @@ public class PersistenceProviderUnitTests { @Before public void setup() { + + PersistenceProvider.CACHE.clear(); + this.shadowingClassLoader = new ShadowingClassLoader(getClass().getClassLoader()); } @@ -80,12 +84,25 @@ public class PersistenceProviderUnitTests { assertThat(fromEntityManager(em), is(HIBERNATE)); } + @Test // DATAJPA-1379 + public void detectsProviderFromProxiedEntityManager() throws Exception { + + shadowingClassLoader.excludePackage("org.eclipse.persistence.jpa"); + + EntityManager em = mockProviderSpecificEntityManagerInterface(ECLIPSELINK_ENTITY_MANAGER_INTERFACE); + + EntityManager emProxy = Mockito.mock(EntityManager.class); + Mockito.when(emProxy.getDelegate()).thenReturn(em); + + assertThat(fromEntityManager(emProxy), is(ECLIPSELINK)); + } + private EntityManager mockProviderSpecificEntityManagerInterface(String interfaceName) throws ClassNotFoundException { Class providerSpecificEntityManagerInterface = InterfaceGenerator.generate(interfaceName, shadowingClassLoader, EntityManager.class); - EntityManager em = EntityManager.class.cast(Mockito.mock(providerSpecificEntityManagerInterface)); + EntityManager em = (EntityManager) Mockito.mock(providerSpecificEntityManagerInterface); Mockito.when(em.getDelegate()).thenReturn(em); // delegate is used to determine the classloader of the provider // specific interface, therefore we return the proxied // EntityManager.