Skip to content

Commit 687c658

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 687c658

2 files changed

Lines changed: 28 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: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.HashMap;
2020
import java.util.List;
2121
import java.util.Map;
22+
import java.util.Optional;
2223

2324
import javax.sql.DataSource;
2425

@@ -29,6 +30,7 @@
2930

3031
import org.springframework.beans.factory.BeanFactory;
3132
import org.springframework.beans.factory.ObjectProvider;
33+
import org.springframework.beans.factory.annotation.Qualifier;
3234
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
3335
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3436
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
@@ -124,8 +126,10 @@ public JpaVendorAdapter jpaVendorAdapter() {
124126
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
125127
ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
126128
ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers,
127-
Map<String, AsyncTaskExecutor> taskExecutors) {
128-
@Nullable AsyncTaskExecutor bootstrapExecutor = determineBootstrapExecutor(taskExecutors);
129+
ObjectProvider<AsyncTaskExecutor> taskExecutors,
130+
@Qualifier(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) Optional<AsyncTaskExecutor> applicationTaskExecutor) {
131+
@Nullable AsyncTaskExecutor bootstrapExecutor = determineBootstrapExecutor(taskExecutors,
132+
applicationTaskExecutor.orElse(null));
129133
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
130134
this::buildJpaProperties, persistenceUnitManager.getIfAvailable(), null, bootstrapExecutor);
131135
if (this.properties.getBootstrap() == Bootstrap.ASYNC) {
@@ -136,9 +140,10 @@ public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter
136140
return builder;
137141
}
138142

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);
143+
private @Nullable AsyncTaskExecutor determineBootstrapExecutor(ObjectProvider<AsyncTaskExecutor> taskExecutors,
144+
@Nullable AsyncTaskExecutor applicationTaskExecutor) {
145+
@Nullable AsyncTaskExecutor asyncTaskExecutor = taskExecutors.getIfUnique();
146+
return (asyncTaskExecutor != null) ? asyncTaskExecutor : applicationTaskExecutor;
142147
}
143148

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

0 commit comments

Comments
 (0)