Polishing.
Revise PersistenceProvider detection to a EntityManagerFactory-based variant, considering EntityManagerFactory proxying. See: #3425 Original pull request: #3885
This commit is contained in:
@@ -25,12 +25,14 @@ import jakarta.persistence.metamodel.IdentifiableType;
|
||||
import jakarta.persistence.metamodel.Metamodel;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.persistence.config.QueryHints;
|
||||
import org.eclipse.persistence.jpa.JpaQuery;
|
||||
@@ -41,6 +43,8 @@ import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aop.framework.AopProxyUtils;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -56,22 +60,15 @@ import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
* @author Jens Schauder
|
||||
* @author Greg Turnquist
|
||||
* @author Yuriy Tsarkov
|
||||
* @author Ariel Morelli Andres (Atlassian US, Inc.)
|
||||
* @author Ariel Morelli Andres
|
||||
*/
|
||||
public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, QueryComment {
|
||||
|
||||
/**
|
||||
* Hibernate persistence provider.
|
||||
* <p>
|
||||
* Since Hibernate 4.3 the location of the HibernateEntityManager moved to the org.hibernate.jpa package. In order to
|
||||
* support both locations we interpret both classnames as a Hibernate {@code PersistenceProvider}.
|
||||
*
|
||||
* @see <a href="https://github.com/spring-projects/spring-data-jpa/issues/846">DATAJPA-444</a>
|
||||
*/
|
||||
HIBERNATE(//
|
||||
Collections.singletonList(HIBERNATE_ENTITY_MANAGER_FACTORY_INTERFACE), //
|
||||
Collections.singletonList(HIBERNATE_ENTITY_MANAGER_INTERFACE), //
|
||||
Collections.singletonList(HIBERNATE_JPA_METAMODEL_TYPE)) {
|
||||
HIBERNATE(List.of(HIBERNATE_ENTITY_MANAGER_FACTORY_INTERFACE), //
|
||||
List.of(HIBERNATE_JPA_METAMODEL_TYPE)) {
|
||||
|
||||
@Override
|
||||
public @Nullable String extractQueryString(Object query) {
|
||||
@@ -136,9 +133,7 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
/**
|
||||
* EclipseLink persistence provider.
|
||||
*/
|
||||
ECLIPSELINK(List.of(ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE1, ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE2),
|
||||
Collections.singleton(ECLIPSELINK_ENTITY_MANAGER_INTERFACE),
|
||||
Collections.singleton(ECLIPSELINK_JPA_METAMODEL_TYPE)) {
|
||||
ECLIPSELINK(List.of(ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE), List.of(ECLIPSELINK_JPA_METAMODEL_TYPE)) {
|
||||
|
||||
@Override
|
||||
public String extractQueryString(Object query) {
|
||||
@@ -180,8 +175,7 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
/**
|
||||
* Unknown special provider. Use standard JPA.
|
||||
*/
|
||||
GENERIC_JPA(Collections.singleton(GENERIC_JPA_ENTITY_MANAGER_INTERFACE),
|
||||
Collections.singleton(GENERIC_JPA_ENTITY_MANAGER_INTERFACE), Collections.emptySet()) {
|
||||
GENERIC_JPA(List.of(GENERIC_JPA_ENTITY_MANAGER_FACTORY_INTERFACE), Collections.emptySet()) {
|
||||
|
||||
@Override
|
||||
public @Nullable String extractQueryString(Object query) {
|
||||
@@ -231,8 +225,7 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
private static final Collection<PersistenceProvider> ALL = List.of(HIBERNATE, ECLIPSELINK, GENERIC_JPA);
|
||||
|
||||
private static final ConcurrentReferenceHashMap<Class<?>, PersistenceProvider> CACHE = new ConcurrentReferenceHashMap<>();
|
||||
private final Iterable<String> entityManagerFactoryClassNames;
|
||||
private final Iterable<String> entityManagerClassNames;
|
||||
final Iterable<String> entityManagerFactoryClassNames;
|
||||
private final Iterable<String> metamodelClassNames;
|
||||
|
||||
private final boolean present;
|
||||
@@ -242,37 +235,15 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
*
|
||||
* @param entityManagerFactoryClassNames the names of the provider specific
|
||||
* {@link jakarta.persistence.EntityManagerFactory} implementations. Must not be {@literal null} or empty.
|
||||
* @param entityManagerClassNames the names of the provider specific {@link EntityManager} implementations. Must not
|
||||
* be {@literal null} or empty.
|
||||
* @param metamodelClassNames must not be {@literal null}.
|
||||
* @param metamodelClassNames the names of the provider specific {@link Metamodel} implementations. Must not be
|
||||
* {@literal null} or empty.
|
||||
*/
|
||||
PersistenceProvider(Iterable<String> entityManagerFactoryClassNames, Iterable<String> entityManagerClassNames,
|
||||
Iterable<String> metamodelClassNames) {
|
||||
PersistenceProvider(Collection<String> entityManagerFactoryClassNames, Collection<String> metamodelClassNames) {
|
||||
|
||||
this.entityManagerFactoryClassNames = entityManagerFactoryClassNames;
|
||||
this.entityManagerClassNames = entityManagerClassNames;
|
||||
this.metamodelClassNames = metamodelClassNames;
|
||||
|
||||
boolean present = false;
|
||||
for (String emfClassName : entityManagerFactoryClassNames) {
|
||||
|
||||
if (ClassUtils.isPresent(emfClassName, PersistenceProvider.class.getClassLoader())) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!present) {
|
||||
for (String entityManagerClassName : entityManagerClassNames) {
|
||||
|
||||
if (ClassUtils.isPresent(entityManagerClassName, PersistenceProvider.class.getClassLoader())) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.present = present;
|
||||
this.present = Stream.concat(entityManagerFactoryClassNames.stream(), metamodelClassNames.stream())
|
||||
.anyMatch(it -> ClassUtils.isPresent(it, PersistenceProvider.class.getClassLoader()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,32 +259,23 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link PersistenceProvider} from the given {@link EntityManager}. If no special one can be
|
||||
* Determines the {@link PersistenceProvider} from the given {@link EntityManager} by introspecting
|
||||
* {@link EntityManagerFactory} via {@link EntityManager#getEntityManagerFactory()}. If no special one can be
|
||||
* determined {@link #GENERIC_JPA} will be returned.
|
||||
* <p>
|
||||
* This method avoids {@link EntityManager} initialization when using
|
||||
* {@link org.springframework.orm.jpa.SharedEntityManagerCreator} by accessing
|
||||
* {@link EntityManager#getEntityManagerFactory()}.
|
||||
*
|
||||
* @param em must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
* @see org.springframework.orm.jpa.SharedEntityManagerCreator
|
||||
*/
|
||||
public static PersistenceProvider fromEntityManager(EntityManager em) {
|
||||
|
||||
Assert.notNull(em, "EntityManager must not be null");
|
||||
|
||||
Class<?> entityManagerType = em.getDelegate().getClass();
|
||||
PersistenceProvider cachedProvider = CACHE.get(entityManagerType);
|
||||
|
||||
if (cachedProvider != null) {
|
||||
return cachedProvider;
|
||||
}
|
||||
|
||||
for (PersistenceProvider provider : ALL) {
|
||||
for (String entityManagerClassName : provider.entityManagerClassNames) {
|
||||
if (isEntityManagerOfType(em, entityManagerClassName)) {
|
||||
return cacheAndReturn(entityManagerType, provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cacheAndReturn(entityManagerType, GENERIC_JPA);
|
||||
return fromEntityManagerFactory(em.getEntityManagerFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,12 +284,24 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
*
|
||||
* @param emf must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
* @since 3.5.1
|
||||
*/
|
||||
public static PersistenceProvider fromEntityManagerFactory(EntityManagerFactory emf) {
|
||||
|
||||
Assert.notNull(emf, "EntityManagerFactory must not be null");
|
||||
|
||||
Class<?> entityManagerType = emf.getPersistenceUnitUtil().getClass();
|
||||
EntityManagerFactory unwrapped = emf;
|
||||
|
||||
while (Proxy.isProxyClass(unwrapped.getClass()) || AopUtils.isAopProxy(unwrapped)) {
|
||||
|
||||
if (Proxy.isProxyClass(unwrapped.getClass())) {
|
||||
unwrapped = unwrapped.unwrap(null);
|
||||
} else if (AopUtils.isAopProxy(unwrapped)) {
|
||||
unwrapped = (EntityManagerFactory) AopProxyUtils.getSingletonTarget(unwrapped);
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> entityManagerType = unwrapped.getClass();
|
||||
PersistenceProvider cachedProvider = CACHE.get(entityManagerType);
|
||||
|
||||
if (cachedProvider != null) {
|
||||
@@ -336,8 +310,7 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
|
||||
for (PersistenceProvider provider : ALL) {
|
||||
for (String emfClassName : provider.entityManagerFactoryClassNames) {
|
||||
if (isOfType(emf.getPersistenceUnitUtil(), emfClassName,
|
||||
emf.getPersistenceUnitUtil().getClass().getClassLoader())) {
|
||||
if (isOfType(unwrapped, emfClassName, unwrapped.getClass().getClassLoader())) {
|
||||
return cacheAndReturn(entityManagerType, provider);
|
||||
}
|
||||
}
|
||||
@@ -445,16 +418,14 @@ public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor, Quer
|
||||
String GENERIC_JPA_ENTITY_MANAGER_FACTORY_INTERFACE = "jakarta.persistence.EntityManagerFactory";
|
||||
String GENERIC_JPA_ENTITY_MANAGER_INTERFACE = "jakarta.persistence.EntityManager";
|
||||
|
||||
String ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE1 = "org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate";
|
||||
String ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE2 = "org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl";
|
||||
String ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE = "org.eclipse.persistence.jpa.JpaEntityManagerFactory";
|
||||
String ECLIPSELINK_ENTITY_MANAGER_INTERFACE = "org.eclipse.persistence.jpa.JpaEntityManager";
|
||||
String ECLIPSELINK_JPA_METAMODEL_TYPE = "org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl";
|
||||
|
||||
// needed as Spring only exposes that interface via the EM proxy
|
||||
String HIBERNATE_ENTITY_MANAGER_FACTORY_INTERFACE = "org.hibernate.jpa.internal.PersistenceUnitUtilImpl";
|
||||
String HIBERNATE_ENTITY_MANAGER_INTERFACE = "org.hibernate.engine.spi.SessionImplementor";
|
||||
|
||||
String HIBERNATE_ENTITY_MANAGER_FACTORY_INTERFACE = "org.hibernate.SessionFactory";
|
||||
String HIBERNATE_ENTITY_MANAGER_INTERFACE = "org.hibernate.Session";
|
||||
String HIBERNATE_JPA_METAMODEL_TYPE = "org.hibernate.metamodel.model.domain.JpaMetamodel";
|
||||
String ECLIPSELINK_JPA_METAMODEL_TYPE = "org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl";
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
package org.springframework.data.jpa.provider;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.jpa.provider.PersistenceProvider.*;
|
||||
import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.assertj.core.api.Assumptions;
|
||||
import org.hibernate.Version;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.asm.ClassWriter;
|
||||
@@ -42,6 +44,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Jens Schauder
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class PersistenceProviderUnitTests {
|
||||
|
||||
@@ -56,12 +59,32 @@ class PersistenceProviderUnitTests {
|
||||
this.shadowingClassLoader = new ShadowingClassLoader(getClass().getClassLoader());
|
||||
}
|
||||
|
||||
@ParameterizedTest // GH-3425
|
||||
@EnumSource(PersistenceProvider.class)
|
||||
void entityManagerFactoryClassNamesAreInterfaces(PersistenceProvider provider) throws ClassNotFoundException {
|
||||
|
||||
for (String className : provider.entityManagerFactoryClassNames) {
|
||||
assertThat(ClassUtils.forName(className, PersistenceProvider.class.getClassLoader()).isInterface()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest // GH-3425
|
||||
@EnumSource(PersistenceProvider.class)
|
||||
void metaModelNamesExist(PersistenceProvider provider) throws ClassNotFoundException {
|
||||
|
||||
for (String className : provider.entityManagerFactoryClassNames) {
|
||||
assertThat(ClassUtils.forName(className, PersistenceProvider.class.getClassLoader()).isInterface()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectsEclipseLinkPersistenceProvider() throws Exception {
|
||||
|
||||
shadowingClassLoader.excludePackage("org.eclipse.persistence.jpa");
|
||||
|
||||
EntityManager em = mockProviderSpecificEntityManagerInterface(ECLIPSELINK_ENTITY_MANAGER_INTERFACE);
|
||||
when(em.getEntityManagerFactory())
|
||||
.thenReturn(mockProviderSpecificEntityManagerFactoryInterface(ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE));
|
||||
|
||||
assertThat(fromEntityManager(em)).isEqualTo(ECLIPSELINK);
|
||||
}
|
||||
@@ -70,31 +93,19 @@ class PersistenceProviderUnitTests {
|
||||
void fallbackToGenericJpaForUnknownPersistenceProvider() throws Exception {
|
||||
|
||||
EntityManager em = mockProviderSpecificEntityManagerInterface("foo.bar.unknown.jpa.JpaEntityManager");
|
||||
when(em.getEntityManagerFactory()).thenReturn(mock(EntityManagerFactory.class));
|
||||
|
||||
assertThat(fromEntityManager(em)).isEqualTo(GENERIC_JPA);
|
||||
}
|
||||
|
||||
@Test // DATAJPA-1019
|
||||
void detectsHibernatePersistenceProviderForHibernateVersion52() throws Exception {
|
||||
|
||||
Assumptions.assumeThat(Version.getVersionString()).startsWith("5.2");
|
||||
|
||||
shadowingClassLoader.excludePackage("org.hibernate");
|
||||
|
||||
EntityManager em = mockProviderSpecificEntityManagerInterface(HIBERNATE_ENTITY_MANAGER_INTERFACE);
|
||||
|
||||
assertThat(fromEntityManager(em)).isEqualTo(HIBERNATE);
|
||||
}
|
||||
|
||||
@Test // DATAJPA-1379
|
||||
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);
|
||||
when(emProxy.getEntityManagerFactory())
|
||||
.thenReturn(mockProviderSpecificEntityManagerFactoryInterface(ECLIPSELINK_ENTITY_MANAGER_FACTORY_INTERFACE));
|
||||
|
||||
assertThat(fromEntityManager(emProxy)).isEqualTo(ECLIPSELINK);
|
||||
}
|
||||
@@ -105,13 +116,23 @@ class PersistenceProviderUnitTests {
|
||||
EntityManager.class);
|
||||
|
||||
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.
|
||||
|
||||
// delegate is used to determine the classloader of the provider
|
||||
// specific interface, therefore we return the proxied EntityManager
|
||||
when(em.getDelegate()).thenReturn(em);
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
private EntityManagerFactory mockProviderSpecificEntityManagerFactoryInterface(String interfaceName)
|
||||
throws ClassNotFoundException {
|
||||
|
||||
Class<?> providerSpecificEntityManagerInterface = InterfaceGenerator.generate(interfaceName, shadowingClassLoader,
|
||||
EntityManager.class);
|
||||
|
||||
return (EntityManagerFactory) Mockito.mock(providerSpecificEntityManagerInterface);
|
||||
}
|
||||
|
||||
static class InterfaceGenerator implements Opcodes {
|
||||
|
||||
static Class<?> generate(final String interfaceName, ClassLoader parentClassLoader, final Class<?>... interfaces)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2025 the original author or authors.
|
||||
* Copyright 2025 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.
|
||||
@@ -21,18 +21,19 @@ import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* {@code CurrentTenantIdentifierResolver} instance for testing
|
||||
* {@code CurrentTenantIdentifierResolver} instance for testing.
|
||||
*
|
||||
* @author Ariel Morelli Andres (Atlassian US, Inc.)
|
||||
* @author Ariel Morelli Andres
|
||||
*/
|
||||
public class HibernateCurrentTenantIdentifierResolver implements CurrentTenantIdentifierResolver<String> {
|
||||
|
||||
private static final ThreadLocal<@Nullable String> CURRENT_TENANT_IDENTIFIER = new ThreadLocal<>();
|
||||
|
||||
public static void setTenantIdentifier(String tenantIdentifier) {
|
||||
static void setTenantIdentifier(String tenantIdentifier) {
|
||||
CURRENT_TENANT_IDENTIFIER.set(tenantIdentifier);
|
||||
}
|
||||
|
||||
public static void removeTenantIdentifier() {
|
||||
static void removeTenantIdentifier() {
|
||||
CURRENT_TENANT_IDENTIFIER.remove();
|
||||
}
|
||||
|
||||
@@ -46,4 +47,5 @@ public class HibernateCurrentTenantIdentifierResolver implements CurrentTenantId
|
||||
public boolean validateExistingCurrentSessions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2025 the original author or authors.
|
||||
* Copyright 2025 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.
|
||||
@@ -18,11 +18,14 @@ package org.springframework.data.jpa.repository;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assumptions.*;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -36,16 +39,14 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* Tests for repositories that use multi-tenancy. This tests verifies that repositories can be created an injected
|
||||
* despite not having a tenant available at creation time
|
||||
* despite not having a tenant available at creation time.
|
||||
*
|
||||
* @author Ariel Morelli Andres (Atlassian US, Inc.)
|
||||
* @author Ariel Morelli Andres
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration()
|
||||
@ContextConfiguration
|
||||
class HibernateMultitenancyTests {
|
||||
|
||||
@Autowired RoleRepository roleRepository;
|
||||
@@ -56,19 +57,23 @@ class HibernateMultitenancyTests {
|
||||
HibernateCurrentTenantIdentifierResolver.removeTenantIdentifier();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // GH-3425
|
||||
void testPersistenceProviderFromFactoryWithoutTenant() {
|
||||
PersistenceProvider provider = PersistenceProvider.fromEntityManagerFactory(em.getEntityManagerFactory());
|
||||
|
||||
PersistenceProvider provider = PersistenceProvider.fromEntityManager(em);
|
||||
|
||||
assumeThat(provider).isEqualTo(PersistenceProvider.HIBERNATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // GH-3425
|
||||
void testRepositoryWithTenant() {
|
||||
|
||||
HibernateCurrentTenantIdentifierResolver.setTenantIdentifier("tenant-id");
|
||||
|
||||
assertThatNoException().isThrownBy(() -> roleRepository.findAll());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // GH-3425
|
||||
void testRepositoryWithoutTenantFails() {
|
||||
assertThatThrownBy(() -> roleRepository.findAll()).isInstanceOf(RuntimeException.class);
|
||||
}
|
||||
@@ -80,9 +85,10 @@ class HibernateMultitenancyTests {
|
||||
return roleRepository.findAll();
|
||||
}
|
||||
|
||||
@ImportResource({ "classpath:multitenancy-test.xml" })
|
||||
@ImportResource("classpath:multitenancy-test.xml")
|
||||
@Configuration
|
||||
@EnableJpaRepositories(basePackageClasses = HibernateRepositoryTests.class, considerNestedRepositories = true,
|
||||
includeFilters = @ComponentScan.Filter(classes = { RoleRepository.class }, type = FilterType.ASSIGNABLE_TYPE))
|
||||
static class TestConfig {}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.jpa.repository.support;
|
||||
import static java.util.Collections.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.jpa.domain.Specification.*;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import jakarta.persistence.EntityManager;
|
||||
@@ -43,6 +42,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
@@ -59,7 +59,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* @author Jens Schauder
|
||||
* @author Greg Turnquist
|
||||
* @author Yanming Zhou
|
||||
* @author Ariel Morelli Andres (Atlassian US, Inc.)
|
||||
* @author Ariel Morelli Andres
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@@ -189,7 +189,6 @@ class SimpleJpaRepositoryUnitTests {
|
||||
newUser.setId(null);
|
||||
|
||||
when(em.getEntityManagerFactory()).thenReturn(entityManagerFactory);
|
||||
when(entityManagerFactory.getPersistenceUnitUtil()).thenReturn(persistenceUnitUtil);
|
||||
|
||||
repo.delete(newUser);
|
||||
|
||||
@@ -206,7 +205,6 @@ class SimpleJpaRepositoryUnitTests {
|
||||
|
||||
when(information.isNew(newUser)).thenReturn(false);
|
||||
when(em.getEntityManagerFactory()).thenReturn(entityManagerFactory);
|
||||
when(entityManagerFactory.getPersistenceUnitUtil()).thenReturn(persistenceUnitUtil);
|
||||
when(persistenceUnitUtil.getIdentifier(any())).thenReturn(23);
|
||||
when(em.find(User.class, 23)).thenReturn(null);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user