Commit 28888968 authored by Scott Frederick's avatar Scott Frederick Committed by Phillip Webb

Change default BootstrapMode for JPA repositories

Change the default `BootstrapMode` for auto-configured `JpaRepositories`
to `BootstrapMode.DEFERRED` to allow the initialization of
`EntityManagerFactory` to be parallelized for increased startup efficiency.

Prior to this change, the default BootstrapMode for all auto-configured
Spring Data repositories was `BootstrapMode.DEFAULT`.

Closes gh-16230
parent ae3bdc79
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -56,6 +56,7 @@ import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; ...@@ -56,6 +56,7 @@ import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Josh Long * @author Josh Long
* @author Scott Frederick
* @since 1.0.0 * @since 1.0.0
* @see EnableJpaRepositories * @see EnableJpaRepositories
*/ */
...@@ -95,7 +96,7 @@ public class JpaRepositoriesAutoConfiguration { ...@@ -95,7 +96,7 @@ public class JpaRepositoriesAutoConfiguration {
} }
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "bootstrap-mode", @ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "bootstrap-mode",
havingValue = "deferred", matchIfMissing = false) havingValue = "deferred", matchIfMissing = true)
static class DeferredBootstrapMode { static class DeferredBootstrapMode {
} }
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -34,6 +34,7 @@ import org.springframework.util.StringUtils; ...@@ -34,6 +34,7 @@ import org.springframework.util.StringUtils;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Scott Frederick
*/ */
class JpaRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport { class JpaRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
...@@ -56,7 +57,7 @@ class JpaRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupp ...@@ -56,7 +57,7 @@ class JpaRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupp
@Override @Override
protected BootstrapMode getBootstrapMode() { protected BootstrapMode getBootstrapMode() {
return (this.bootstrapMode == null) ? super.getBootstrapMode() : this.bootstrapMode; return (this.bootstrapMode == null) ? BootstrapMode.DEFERRED : this.bootstrapMode;
} }
@Override @Override
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -51,6 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -51,6 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Dave Syer * @author Dave Syer
* @author Oliver Gierke * @author Oliver Gierke
* @author Scott Frederick
*/ */
class JpaRepositoriesAutoConfigurationTests { class JpaRepositoriesAutoConfigurationTests {
...@@ -85,7 +86,7 @@ class JpaRepositoriesAutoConfigurationTests { ...@@ -85,7 +86,7 @@ class JpaRepositoriesAutoConfigurationTests {
} }
@Test @Test
void whenBootstrappingModeIsLazyWithMultipleAsyncExecutorBootstrapExecutorIsConfigured() { void whenBootstrapModeIsLazyWithMultipleAsyncExecutorBootstrapExecutorIsConfigured() {
this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class) this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class)
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class,
TaskSchedulingAutoConfiguration.class)) TaskSchedulingAutoConfiguration.class))
...@@ -96,7 +97,7 @@ class JpaRepositoriesAutoConfigurationTests { ...@@ -96,7 +97,7 @@ class JpaRepositoriesAutoConfigurationTests {
} }
@Test @Test
void whenBootstrappingModeIsLazyWithSingleAsyncExecutorBootstrapExecutorIsConfigured() { void whenBootstrapModeIsLazyWithSingleAsyncExecutorBootstrapExecutorIsConfigured() {
this.contextRunner.withUserConfiguration(SingleAsyncTaskExecutorConfiguration.class) this.contextRunner.withUserConfiguration(SingleAsyncTaskExecutorConfiguration.class)
.withPropertyValues("spring.data.jpa.repositories.bootstrap-mode=lazy") .withPropertyValues("spring.data.jpa.repositories.bootstrap-mode=lazy")
.run((context) -> assertThat( .run((context) -> assertThat(
...@@ -105,7 +106,7 @@ class JpaRepositoriesAutoConfigurationTests { ...@@ -105,7 +106,7 @@ class JpaRepositoriesAutoConfigurationTests {
} }
@Test @Test
void whenBootstrappingModeIsDeferredBootstrapExecutorIsConfigured() { void whenBootstrapModeIsDeferredBootstrapExecutorIsConfigured() {
this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class) this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class)
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class,
TaskSchedulingAutoConfiguration.class)) TaskSchedulingAutoConfiguration.class))
...@@ -116,7 +117,7 @@ class JpaRepositoriesAutoConfigurationTests { ...@@ -116,7 +117,7 @@ class JpaRepositoriesAutoConfigurationTests {
} }
@Test @Test
void whenBootstrappingModeIsDefaultBootstrapExecutorIsNotConfigured() { void whenBootstrapModeIsDefaultBootstrapExecutorIsNotConfigured() {
this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class) this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class)
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class,
TaskSchedulingAutoConfiguration.class)) TaskSchedulingAutoConfiguration.class))
...@@ -124,6 +125,16 @@ class JpaRepositoriesAutoConfigurationTests { ...@@ -124,6 +125,16 @@ class JpaRepositoriesAutoConfigurationTests {
context.getBean(LocalContainerEntityManagerFactoryBean.class).getBootstrapExecutor()).isNull()); context.getBean(LocalContainerEntityManagerFactoryBean.class).getBootstrapExecutor()).isNull());
} }
@Test
void bootstrapModeIsDeferredByDefault() {
this.contextRunner.withUserConfiguration(MultipleAsyncTaskExecutorConfiguration.class)
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class,
TaskSchedulingAutoConfiguration.class))
.run((context) -> assertThat(
context.getBean(LocalContainerEntityManagerFactoryBean.class).getBootstrapExecutor())
.isEqualTo(context.getBean("applicationTaskExecutor")));
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableScheduling @EnableScheduling
@Import(TestConfiguration.class) @Import(TestConfiguration.class)
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -36,6 +36,7 @@ import org.springframework.boot.test.context.SpringBootTest; ...@@ -36,6 +36,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.data.repository.config.BootstrapMode;
import org.springframework.test.context.BootstrapWith; import org.springframework.test.context.BootstrapWith;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -62,6 +63,7 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -62,6 +63,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Artsiom Yudovin * @author Artsiom Yudovin
* @author Scott Frederick
* @since 1.4.0 * @since 1.4.0
* @see AutoConfigureDataJpa * @see AutoConfigureDataJpa
* @see AutoConfigureTestDatabase * @see AutoConfigureTestDatabase
...@@ -99,6 +101,14 @@ public @interface DataJpaTest { ...@@ -99,6 +101,14 @@ public @interface DataJpaTest {
@PropertyMapping("spring.jpa.show-sql") @PropertyMapping("spring.jpa.show-sql")
boolean showSql() default true; boolean showSql() default true;
/**
* The {@link BootstrapMode} for the test repository support. Defaults to
* {@link BootstrapMode#LAZY}.
* @return the {@link BootstrapMode} to use for test the repository
*/
@PropertyMapping("spring.data.jpa.repositories.bootstrap-mode")
BootstrapMode bootstrapMode() default BootstrapMode.LAZY;
/** /**
* Determines if default filtering should be used with * Determines if default filtering should be used with
* {@link SpringBootApplication @SpringBootApplication}. By default no beans are * {@link SpringBootApplication @SpringBootApplication}. By default no beans are
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -20,17 +20,18 @@ import org.junit.jupiter.api.Test; ...@@ -20,17 +20,18 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.data.repository.config.BootstrapMode;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for the {@link DataJpaTest#properties properties} attribute of * Tests for non-default attributes of {@link DataJpaTest @DataJpaTest}.
* {@link DataJpaTest @DataJpaTest}.
* *
* @author Artsiom Yudovin * @author Artsiom Yudovin
* @author Scott Frederick
*/ */
@DataJpaTest(properties = "spring.profiles.active=test") @DataJpaTest(properties = "spring.profiles.active=test", bootstrapMode = BootstrapMode.DEFERRED)
class DataJpaTestPropertiesIntegrationTests { class DataJpaTestAttributesIntegrationTests {
@Autowired @Autowired
private Environment environment; private Environment environment;
...@@ -40,4 +41,10 @@ class DataJpaTestPropertiesIntegrationTests { ...@@ -40,4 +41,10 @@ class DataJpaTestPropertiesIntegrationTests {
assertThat(this.environment.getActiveProfiles()).containsExactly("test"); assertThat(this.environment.getActiveProfiles()).containsExactly("test");
} }
@Test
void bootstrapModeIsSet() {
assertThat(this.environment.getProperty("spring.data.jpa.repositories.bootstrap-mode"))
.isEqualTo(BootstrapMode.DEFERRED.name());
}
} }
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.data.repository.config.BootstrapMode;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
...@@ -37,6 +38,7 @@ import static org.springframework.boot.test.autoconfigure.AutoConfigurationImpor ...@@ -37,6 +38,7 @@ import static org.springframework.boot.test.autoconfigure.AutoConfigurationImpor
* *
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Scott Frederick
*/ */
@DataJpaTest @DataJpaTest
@TestPropertySource(properties = "spring.jpa.hibernate.use-new-id-generator-mappings=false") @TestPropertySource(properties = "spring.jpa.hibernate.use-new-id-generator-mappings=false")
...@@ -106,4 +108,10 @@ class DataJpaTestIntegrationTests { ...@@ -106,4 +108,10 @@ class DataJpaTestIntegrationTests {
assertThat(this.applicationContext).has(importedAutoConfiguration(LiquibaseAutoConfiguration.class)); assertThat(this.applicationContext).has(importedAutoConfiguration(LiquibaseAutoConfiguration.class));
} }
@Test
void bootstrapModeIsLazyByDefault() {
assertThat(this.applicationContext.getEnvironment().getProperty("spring.data.jpa.repositories.bootstrap-mode"))
.isEqualTo(BootstrapMode.LAZY.name());
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment