Generalize script-based DB initialization and add R2DBC initializer

See gh-24741
This commit is contained in:
Andy Wilkinson
2021-03-26 15:14:47 +00:00
parent eb1200415d
commit 9cc7f0b54d
16 changed files with 361 additions and 112 deletions

View File

@@ -41,9 +41,9 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceInitializationConfi
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.jdbc.init.DataSourceInitializationSettings;
import org.springframework.boot.jdbc.init.ScriptDataSourceInitializer;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.DependsOn;
@@ -56,7 +56,7 @@ import org.springframework.util.StringUtils;
/**
* Configuration for {@link DataSource} initialization using a
* {@link ScriptDataSourceInitializer} with DDL and DML scripts.
* {@link DataSourceScriptDatabaseInitializer} with DDL and DML scripts.
*
* @author Andy Wilkinson
*/
@@ -87,13 +87,13 @@ class DataSourceInitializationConfiguration {
@org.springframework.context.annotation.Conditional(DifferentCredentialsCondition.class)
@org.springframework.context.annotation.Import(DataSourceInitializationDependencyConfigurer.class)
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean(ScriptDataSourceInitializer.class)
@ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class)
static class InitializationSpecificCredentialsDataSourceInitializationConfiguration {
@Bean
ScriptDataSourceInitializer ddlOnlyScriptDataSourceInitializer(ObjectProvider<DataSource> dataSource,
DataSourceScriptDatabaseInitializer ddlOnlyScriptDataSourceInitializer(ObjectProvider<DataSource> dataSource,
DataSourceProperties properties, ResourceLoader resourceLoader) {
DataSourceInitializationSettings settings = new DataSourceInitializationSettings();
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(scriptLocations(properties.getSchema(), "schema", properties.getPlatform()));
settings.setContinueOnError(properties.isContinueOnError());
settings.setSeparator(properties.getSeparator());
@@ -106,9 +106,9 @@ class DataSourceInitializationConfiguration {
@Bean
@DependsOn("ddlOnlyScriptDataSourceInitializer")
ScriptDataSourceInitializer dmlOnlyScriptDataSourceInitializer(ObjectProvider<DataSource> dataSource,
DataSourceScriptDatabaseInitializer dmlOnlyScriptDataSourceInitializer(ObjectProvider<DataSource> dataSource,
DataSourceProperties properties, ResourceLoader resourceLoader) {
DataSourceInitializationSettings settings = new DataSourceInitializationSettings();
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setDataLocations(scriptLocations(properties.getData(), "data", properties.getPlatform()));
settings.setContinueOnError(properties.isContinueOnError());
settings.setSeparator(properties.getSeparator());
@@ -144,13 +144,13 @@ class DataSourceInitializationConfiguration {
@org.springframework.context.annotation.Import(DataSourceInitializationDependencyConfigurer.class)
@org.springframework.context.annotation.Conditional(DataSourceInitializationCondition.class)
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean(ScriptDataSourceInitializer.class)
@ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class)
static class SharedCredentialsDataSourceInitializationConfiguration {
@Bean
ScriptDataSourceInitializer scriptDataSourceInitializer(DataSource dataSource, DataSourceProperties properties,
ResourceLoader resourceLoader) {
DataSourceInitializationSettings settings = new DataSourceInitializationSettings();
DataSourceScriptDatabaseInitializer scriptDataSourceInitializer(DataSource dataSource,
DataSourceProperties properties, ResourceLoader resourceLoader) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(scriptLocations(properties.getSchema(), "schema", properties.getPlatform()));
settings.setDataLocations(scriptLocations(properties.getData(), "data", properties.getPlatform()));
settings.setContinueOnError(properties.isContinueOnError());
@@ -188,12 +188,12 @@ class DataSourceInitializationConfiguration {
}
static class InitializationModeDataSourceScriptDatabaseInitializer extends ScriptDataSourceInitializer {
static class InitializationModeDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer {
private final DataSourceInitializationMode mode;
InitializationModeDataSourceScriptDatabaseInitializer(DataSource dataSource,
DataSourceInitializationSettings settings, DataSourceInitializationMode mode) {
DatabaseInitializationSettings settings, DataSourceInitializationMode mode) {
super(dataSource, settings);
this.mode = mode;
}

View File

@@ -29,9 +29,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandi
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.init.DataSourceInitializationSettings;
import org.springframework.boot.jdbc.init.ScriptDataSourceInitializer;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DataSourceInitializationDependencyConfigurer;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -45,7 +45,7 @@ import org.springframework.util.StringUtils;
* @since 2.5.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(ScriptDataSourceInitializer.class)
@ConditionalOnMissingBean(DataSourceScriptDatabaseInitializer.class)
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnProperty(prefix = "spring.sql.init", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@@ -54,15 +54,15 @@ import org.springframework.util.StringUtils;
public class SqlInitializationAutoConfiguration {
@Bean
ScriptDataSourceInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource,
DataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource,
SqlInitializationProperties initializationProperties) {
DataSourceInitializationSettings settings = createSettings(initializationProperties);
return new ScriptDataSourceInitializer(determineDataSource(dataSource, initializationProperties.getUsername(),
initializationProperties.getPassword()), settings);
DatabaseInitializationSettings settings = createSettings(initializationProperties);
return new DataSourceScriptDatabaseInitializer(determineDataSource(dataSource,
initializationProperties.getUsername(), initializationProperties.getPassword()), settings);
}
private static DataSourceInitializationSettings createSettings(SqlInitializationProperties properties) {
DataSourceInitializationSettings settings = new DataSourceInitializationSettings();
private static DatabaseInitializationSettings createSettings(SqlInitializationProperties properties) {
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
settings.setSchemaLocations(
scriptLocations(properties.getSchemaLocations(), "schema", properties.getPlatform()));
settings.setDataLocations(scriptLocations(properties.getDataLocations(), "data", properties.getPlatform()));

View File

@@ -43,7 +43,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.jdbc.init.ScriptDataSourceInitializer;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.jdbc.init.dependency.DependsOnDataSourceInitialization;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
@@ -240,14 +240,15 @@ class DataSourceAutoConfigurationTests {
void testDataSourceIsInitializedEarly() {
this.contextRunner.withUserConfiguration(TestInitializedDataSourceConfiguration.class)
.withPropertyValues("spring.datasource.initialization-mode=always").run((context) -> {
assertThat(context).hasSingleBean(ScriptDataSourceInitializer.class);
assertThat(context).hasSingleBean(DataSourceScriptDatabaseInitializer.class);
assertThat(context.getBean(TestInitializedDataSourceConfiguration.class).called).isTrue();
});
}
@Test
void whenNoInitializationRelatedSpringDataSourcePropertiesAreConfiguredThenInitializationBacksOff() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ScriptDataSourceInitializer.class));
this.contextRunner
.run((context) -> assertThat(context).doesNotHaveBean(DataSourceScriptDatabaseInitializer.class));
}
private static Function<ApplicationContextRunner, ApplicationContextRunner> hideConnectionPools() {