Skip to content

Commit b92fb64

Browse files
committed
Improve JpaBaseConfiguration to resolve beans lazily to avoid circular reference
Fix GH-50797 and GH-50749 Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
1 parent e16c5d0 commit b92fb64

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

module/spring-boot-hibernate/src/test/java/org/springframework/boot/hibernate/autoconfigure/HibernateJpaAutoConfigurationTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,15 @@ void whenSpringJpaGenerateDdlIsTrueSpringJpaHibernateDdlAutoIsCreateAndJakartaSc
10171017
.run((context) -> assertThat(tablesFrom(context)).doesNotContain("CITY"));
10181018
}
10191019

1020+
@Test // GH-50797
1021+
void circularReference() {
1022+
this.contextRunner.withUserConfiguration(CircularReferenceConfiguration.class).run((context) -> {
1023+
assertThat(context).hasSingleBean(DataSource.class);
1024+
assertThat(context).hasSingleBean(JpaTransactionManager.class);
1025+
assertThat(context).hasSingleBean(EntityManagerFactory.class);
1026+
});
1027+
}
1028+
10201029
private List<String> tablesFrom(AssertableApplicationContext context) {
10211030
DataSource dataSource = context.getBean(DataSource.class);
10221031
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
@@ -1474,4 +1483,13 @@ SimpleAsyncTaskExecutor applicationTaskExecutor() {
14741483

14751484
}
14761485

1486+
@Configuration
1487+
static class CircularReferenceConfiguration extends MultipleAsyncTaskExecutorsConfiguration {
1488+
1489+
CircularReferenceConfiguration(PlatformTransactionManager transactionManager) {
1490+
1491+
}
1492+
1493+
}
1494+
14771495
}

module/spring-boot-jpa/src/main/java/org/springframework/boot/jpa/autoconfigure/JpaBaseConfiguration.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.springframework.beans.factory.BeanFactory;
3131
import org.springframework.beans.factory.ObjectProvider;
32+
import org.springframework.beans.factory.annotation.Qualifier;
3233
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
3334
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3435
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
@@ -124,8 +125,9 @@ public JpaVendorAdapter jpaVendorAdapter() {
124125
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
125126
ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
126127
ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers,
127-
Map<String, AsyncTaskExecutor> taskExecutors) {
128-
@Nullable AsyncTaskExecutor bootstrapExecutor = determineBootstrapExecutor(taskExecutors);
128+
ObjectProvider<AsyncTaskExecutor> taskExecutors,
129+
@Qualifier(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) ObjectProvider<AsyncTaskExecutor> applicationTaskExecutor) {
130+
@Nullable AsyncTaskExecutor bootstrapExecutor = determineBootstrapExecutor(taskExecutors, applicationTaskExecutor);
129131
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
130132
this::buildJpaProperties, persistenceUnitManager.getIfAvailable(), null, bootstrapExecutor);
131133
if (this.properties.getBootstrap() == Bootstrap.ASYNC) {
@@ -136,9 +138,10 @@ public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter
136138
return builder;
137139
}
138140

139-
private @Nullable AsyncTaskExecutor determineBootstrapExecutor(Map<String, AsyncTaskExecutor> taskExecutors) {
140-
return (taskExecutors.size() == 1) ? taskExecutors.values().iterator().next()
141-
: taskExecutors.get(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
141+
private @Nullable AsyncTaskExecutor determineBootstrapExecutor(ObjectProvider<AsyncTaskExecutor> taskExecutors,
142+
ObjectProvider<AsyncTaskExecutor> applicationTaskExecutor) {
143+
@Nullable AsyncTaskExecutor asyncTaskExecutor = taskExecutors.getIfUnique();
144+
return (asyncTaskExecutor != null) ? asyncTaskExecutor : applicationTaskExecutor.getIfAvailable();
142145
}
143146

144147
private Map<String, ?> buildJpaProperties(DataSource dataSource) {

0 commit comments

Comments
 (0)