Ensure that JPA metamodel cache is cleared when lazy init is enabled

Closes gh-46630
This commit is contained in:
Andy Wilkinson
2025-07-31 11:22:54 +01:00
parent c9c80763b7
commit 85fb93ef64
2 changed files with 25 additions and 0 deletions
@@ -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<String, AsyncTaskExecutor> taskExecutors) {
if (taskExecutors.size() == 1) {
return taskExecutors.values().iterator().next();
@@ -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<Metamodel, JpaMetamodel> jpaMetamodelCache() {
return (Map<Metamodel, JpaMetamodel>) ReflectionTestUtils.getField(JpaMetamodel.class, "CACHE");
}
@Configuration(proxyBeanMethods = false)
@EnableScheduling
@Import(TestConfiguration.class)