diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java index 85438fb8eaa..f5047bfadb2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/jpa/JpaRepositoriesAutoConfiguration.java @@ -20,6 +20,7 @@ import java.util.Map; import javax.sql.DataSource; +import org.springframework.boot.LazyInitializationExcludeFilter; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; @@ -91,6 +92,11 @@ public class JpaRepositoriesAutoConfiguration { }; } + @Bean + static LazyInitializationExcludeFilter eagerJpaMetamodelCacheCleanup() { + return (name, definition, type) -> "org.springframework.data.jpa.util.JpaMetamodelCacheCleanup".equals(name); + } + private AsyncTaskExecutor determineBootstrapExecutor(Map taskExecutors) { if (taskExecutors.size() == 1) { return taskExecutors.values().iterator().next(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/jpa/AbstractJpaRepositoriesAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/jpa/AbstractJpaRepositoriesAutoConfigurationTests.java index 4a10316d184..d583dde33f4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/jpa/AbstractJpaRepositoriesAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/jpa/AbstractJpaRepositoriesAutoConfigurationTests.java @@ -16,9 +16,13 @@ package org.springframework.boot.autoconfigure.data.jpa; +import java.util.Map; + import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.metamodel.Metamodel; import org.junit.jupiter.api.Test; +import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; @@ -40,8 +44,10 @@ import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Import; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.util.JpaMetamodel; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.PlatformTransactionManager; import static org.assertj.core.api.Assertions.assertThat; @@ -138,6 +144,19 @@ abstract class AbstractJpaRepositoriesAutoConfigurationTests { .isNull()); } + @Test + void whenLazyInitializationIsEnabledJpaMetamodelCacheIsClearedOnContextClose() { + this.contextRunner.withUserConfiguration(TestConfiguration.class) + .withBean(LazyInitializationBeanFactoryPostProcessor.class) + .run((context) -> assertThat(jpaMetamodelCache()).isNotEmpty()); + assertThat(jpaMetamodelCache()).isEmpty(); + } + + @SuppressWarnings("unchecked") + private Map jpaMetamodelCache() { + return (Map) ReflectionTestUtils.getField(JpaMetamodel.class, "CACHE"); + } + @Configuration(proxyBeanMethods = false) @EnableScheduling @Import(TestConfiguration.class)