Commit dbb1e222 authored by Stephane Nicoll's avatar Stephane Nicoll

Initialize only an embedded datasource by default

This commit renames spring.datasource.initialize to
spring.datasource.initialization-mode and use the
DataSourceInitializationMode enum. By default, only an embedded
datasource is initialized.

Closes gh-10773
parent b720c214
...@@ -51,7 +51,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests { ...@@ -51,7 +51,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class,
DataSourceHealthIndicatorAutoConfiguration.class)) DataSourceHealthIndicatorAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialize=false"); .withPropertyValues("spring.datasource.initialization-mode=never");
@Test @Test
public void runShouldCreateIndicator() { public void runShouldCreateIndicator() {
......
...@@ -27,6 +27,8 @@ import org.apache.commons.logging.LogFactory; ...@@ -27,6 +27,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.config.ResourceNotFoundException; import org.springframework.boot.context.config.ResourceNotFoundException;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
...@@ -90,13 +92,13 @@ class DataSourceInitializer { ...@@ -90,13 +92,13 @@ class DataSourceInitializer {
* @see DataSourceProperties#getSchema() * @see DataSourceProperties#getSchema()
*/ */
public boolean createSchema() { public boolean createSchema() {
if (!this.properties.isInitialize()) {
logger.debug("Initialization disabled (not running DDL scripts)");
return false;
}
List<Resource> scripts = getScripts("spring.datasource.schema", List<Resource> scripts = getScripts("spring.datasource.schema",
this.properties.getSchema(), "schema"); this.properties.getSchema(), "schema");
if (!scripts.isEmpty()) { if (!scripts.isEmpty()) {
if (!isEnabled()) {
logger.debug("Initialization disabled (not running DDL scripts)");
return false;
}
String username = this.properties.getSchemaUsername(); String username = this.properties.getSchemaUsername();
String password = this.properties.getSchemaPassword(); String password = this.properties.getSchemaPassword();
runScripts(scripts, username, password); runScripts(scripts, username, password);
...@@ -109,19 +111,41 @@ class DataSourceInitializer { ...@@ -109,19 +111,41 @@ class DataSourceInitializer {
* @see DataSourceProperties#getData() * @see DataSourceProperties#getData()
*/ */
public void initSchema() { public void initSchema() {
if (!this.properties.isInitialize()) {
logger.debug("Initialization disabled (not running data scripts)");
return;
}
List<Resource> scripts = getScripts("spring.datasource.data", List<Resource> scripts = getScripts("spring.datasource.data",
this.properties.getData(), "data"); this.properties.getData(), "data");
if (!scripts.isEmpty()) { if (!scripts.isEmpty()) {
if (!isEnabled()) {
logger.debug("Initialization disabled (not running data scripts)");
return;
}
String username = this.properties.getDataUsername(); String username = this.properties.getDataUsername();
String password = this.properties.getDataPassword(); String password = this.properties.getDataPassword();
runScripts(scripts, username, password); runScripts(scripts, username, password);
} }
} }
private boolean isEnabled() {
DataSourceInitializationMode mode = this.properties.getInitializationMode();
if (mode == DataSourceInitializationMode.NEVER) {
return false;
}
if (mode == DataSourceInitializationMode.EMBEDDED
&& !isEmbedded()) {
return false;
}
return true;
}
private boolean isEmbedded() {
try {
return EmbeddedDatabaseConnection.isEmbedded(this.dataSource);
}
catch (Exception ex) {
logger.debug("Could not determine if datasource is embedded", ex);
return false;
}
}
private List<Resource> getScripts(String propertyName, List<String> resources, private List<Resource> getScripts(String propertyName, List<String> resources,
String fallback) { String fallback) {
if (resources != null) { if (resources != null) {
......
...@@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanCreationException; ...@@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.context.EnvironmentAware; import org.springframework.context.EnvironmentAware;
...@@ -99,9 +100,9 @@ public class DataSourceProperties ...@@ -99,9 +100,9 @@ public class DataSourceProperties
private String jndiName; private String jndiName;
/** /**
* Populate the database using 'data.sql'. * Initialize the datasource using available DDL and DML scripts.
*/ */
private boolean initialize = true; private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED;
/** /**
* Platform to use in the DDL or DML scripts (e.g. schema-${platform}.sql or * Platform to use in the DDL or DML scripts (e.g. schema-${platform}.sql or
...@@ -376,12 +377,12 @@ public class DataSourceProperties ...@@ -376,12 +377,12 @@ public class DataSourceProperties
this.jndiName = jndiName; this.jndiName = jndiName;
} }
public boolean isInitialize() { public DataSourceInitializationMode getInitializationMode() {
return this.initialize; return this.initializationMode;
} }
public void setInitialize(boolean initialize) { public void setInitializationMode(DataSourceInitializationMode initializationMode) {
this.initialize = initialize; this.initializationMode = initializationMode;
} }
public String getPlatform() { public String getPlatform() {
......
...@@ -85,6 +85,10 @@ ...@@ -85,6 +85,10 @@
"description": "Enable JMX support (if provided by the underlying pool).", "description": "Enable JMX support (if provided by the underlying pool).",
"defaultValue": false "defaultValue": false
}, },
{
"name": "spring.datasource.initialization-mode",
"defaultValue": "embedded"
},
{ {
"name": "spring.data.cassandra.compression", "name": "spring.data.cassandra.compression",
"defaultValue": "none" "defaultValue": "none"
...@@ -1031,6 +1035,14 @@ ...@@ -1031,6 +1035,14 @@
"level": "error" "level": "error"
} }
}, },
{
"name": "spring.datasource.initialize",
"defaultValue": true,
"deprecation": {
"replacement": "spring.datasource.initialization-mode",
"level": "error"
}
},
{ {
"name": "spring.http.multipart.enabled", "name": "spring.http.multipart.enabled",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",
......
...@@ -62,7 +62,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -62,7 +62,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
@Test @Test
public void testDefaultRepositoryConfiguration() throws Exception { public void testDefaultRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context); TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(TestConfiguration.class, BaseConfiguration.class); this.context.register(TestConfiguration.class, BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CountryRepository.class)).isNotNull(); assertThat(this.context.getBean(CountryRepository.class)).isNotNull();
...@@ -71,7 +72,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -71,7 +72,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
@Test @Test
public void testMixedRepositoryConfiguration() throws Exception { public void testMixedRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context); TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(MixedConfiguration.class, BaseConfiguration.class); this.context.register(MixedConfiguration.class, BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CountryRepository.class)).isNotNull(); assertThat(this.context.getBean(CountryRepository.class)).isNotNull();
...@@ -81,7 +83,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -81,7 +83,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
@Test @Test
public void testJpaRepositoryConfigurationWithMongoTemplate() throws Exception { public void testJpaRepositoryConfigurationWithMongoTemplate() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context); TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(JpaConfiguration.class, BaseConfiguration.class); this.context.register(JpaConfiguration.class, BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); assertThat(this.context.getBean(CityRepository.class)).isNotNull();
...@@ -90,7 +93,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -90,7 +93,8 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
@Test @Test
public void testJpaRepositoryConfigurationWithMongoOverlap() throws Exception { public void testJpaRepositoryConfigurationWithMongoOverlap() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context); TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(OverlapConfiguration.class, BaseConfiguration.class); this.context.register(OverlapConfiguration.class, BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); assertThat(this.context.getBean(CityRepository.class)).isNotNull();
...@@ -101,7 +105,7 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -101,7 +105,7 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
throws Exception { throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues TestPropertyValues
.of("spring.datasource.initialize:false", .of("spring.datasource.initialization-mode:never",
"spring.data.mongodb.repositories.enabled:false") "spring.data.mongodb.repositories.enabled:false")
.applyTo(this.context); .applyTo(this.context);
this.context.register(OverlapConfiguration.class, BaseConfiguration.class); this.context.register(OverlapConfiguration.class, BaseConfiguration.class);
......
...@@ -58,7 +58,8 @@ public class MongoReactiveAndBlockingRepositoriesAutoConfigurationTests { ...@@ -58,7 +58,8 @@ public class MongoReactiveAndBlockingRepositoriesAutoConfigurationTests {
public void shouldCreateInstancesForReactiveAndBlockingRepositories() public void shouldCreateInstancesForReactiveAndBlockingRepositories()
throws Exception { throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false").applyTo(this.context); TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context);
this.context.register(BlockingAndReactiveConfiguration.class, this.context.register(BlockingAndReactiveConfiguration.class,
BaseConfiguration.class); BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
......
...@@ -93,7 +93,8 @@ public class MixedNeo4jRepositoriesAutoConfigurationTests { ...@@ -93,7 +93,8 @@ public class MixedNeo4jRepositoriesAutoConfigurationTests {
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
TestPropertyValues.of(environment).and("spring.datasource.initialize=false") TestPropertyValues.of(environment)
.and("spring.datasource.initialization-mode=never")
.applyTo(context); .applyTo(context);
context.register(config); context.register(config);
context.register(DataSourceAutoConfiguration.class, context.register(DataSourceAutoConfiguration.class,
......
...@@ -49,7 +49,7 @@ public class HazelcastJpaDependencyAutoConfigurationTests { ...@@ -49,7 +49,7 @@ public class HazelcastJpaDependencyAutoConfigurationTests {
HibernateJpaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
HazelcastJpaDependencyAutoConfiguration.class)) HazelcastJpaDependencyAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true", .withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.datasource.initialize=false"); "spring.datasource.initialization-mode=never");
@Test @Test
public void registrationIfHazelcastInstanceHasRegularBeanName() { public void registrationIfHazelcastInstanceHasRegularBeanName() {
......
...@@ -63,7 +63,7 @@ public class DataSourceAutoConfigurationTests { ...@@ -63,7 +63,7 @@ public class DataSourceAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialize=false", .withPropertyValues("spring.datasource.initialization-mode=never",
"spring.datasource.url:jdbc:hsqldb:mem:testdb-" "spring.datasource.url:jdbc:hsqldb:mem:testdb-"
+ new Random().nextInt()); + new Random().nextInt());
...@@ -219,7 +219,7 @@ public class DataSourceAutoConfigurationTests { ...@@ -219,7 +219,7 @@ public class DataSourceAutoConfigurationTests {
public void testDataSourceIsInitializedEarly() { public void testDataSourceIsInitializedEarly() {
this.contextRunner this.contextRunner
.withUserConfiguration(TestInitializedDataSourceConfiguration.class) .withUserConfiguration(TestInitializedDataSourceConfiguration.class)
.withPropertyValues("spring.datasource.initialize=true") .withPropertyValues("spring.datasource.initialization-mode=always")
.run((context) -> assertThat(context .run((context) -> assertThat(context
.getBean(TestInitializedDataSourceConfiguration.class).called) .getBean(TestInitializedDataSourceConfiguration.class).called)
.isTrue()); .isTrue());
......
...@@ -59,13 +59,14 @@ public class DataSourceInitializerInvokerTests { ...@@ -59,13 +59,14 @@ public class DataSourceInitializerInvokerTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner() private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialize=false", .withPropertyValues("spring.datasource.initialization-mode=never",
"spring.datasource.url:jdbc:hsqldb:mem:init-" "spring.datasource.url:jdbc:hsqldb:mem:init-"
+ UUID.randomUUID().toString()); + UUID.randomUUID().toString());
@Test @Test
public void dataSourceInitialized() { public void dataSourceInitialized() {
this.contextRunner.withPropertyValues("spring.datasource.initialize:true") this.contextRunner
.withPropertyValues("spring.datasource.initialization-mode:always")
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(DataSource.class); assertThat(context).hasSingleBean(DataSource.class);
DataSource dataSource = context.getBean(DataSource.class); DataSource dataSource = context.getBean(DataSource.class);
...@@ -77,7 +78,7 @@ public class DataSourceInitializerInvokerTests { ...@@ -77,7 +78,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void initializationAppliesToCustomDataSource() { public void initializationAppliesToCustomDataSource() {
this.contextRunner.withUserConfiguration(OneDataSource.class) this.contextRunner.withUserConfiguration(OneDataSource.class)
.withPropertyValues("spring.datasource.initialize:true") .withPropertyValues("spring.datasource.initialization-mode:always")
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(DataSource.class); assertThat(context).hasSingleBean(DataSource.class);
assertDataSourceIsInitialized(context.getBean(DataSource.class)); assertDataSourceIsInitialized(context.getBean(DataSource.class));
...@@ -93,7 +94,7 @@ public class DataSourceInitializerInvokerTests { ...@@ -93,7 +94,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithExplicitScript() { public void dataSourceInitializedWithExplicitScript() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.datasource.initialize:true", .withPropertyValues("spring.datasource.initialization-mode:always",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("schema.sql"), + getRelativeLocationFor("schema.sql"),
"spring.datasource.data:" + getRelativeLocationFor("data.sql")) "spring.datasource.data:" + getRelativeLocationFor("data.sql"))
...@@ -110,7 +111,8 @@ public class DataSourceInitializerInvokerTests { ...@@ -110,7 +111,8 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithMultipleScripts() { public void dataSourceInitializedWithMultipleScripts() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.datasource.initialize:true", .withPropertyValues(
"spring.datasource.initialization-mode:always",
"spring.datasource.schema:" + getRelativeLocationFor("schema.sql") "spring.datasource.schema:" + getRelativeLocationFor("schema.sql")
+ "," + getRelativeLocationFor("another.sql"), + "," + getRelativeLocationFor("another.sql"),
"spring.datasource.data:" + getRelativeLocationFor("data.sql")) "spring.datasource.data:" + getRelativeLocationFor("data.sql"))
...@@ -128,7 +130,8 @@ public class DataSourceInitializerInvokerTests { ...@@ -128,7 +130,8 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithExplicitSqlScriptEncoding() { public void dataSourceInitializedWithExplicitSqlScriptEncoding() {
this.contextRunner.withPropertyValues("spring.datasource.initialize:true", this.contextRunner.withPropertyValues(
"spring.datasource.initialization-mode:always",
"spring.datasource.sqlScriptEncoding:UTF-8", "spring.datasource.sqlScriptEncoding:UTF-8",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("encoding-schema.sql"), + getRelativeLocationFor("encoding-schema.sql"),
...@@ -155,7 +158,7 @@ public class DataSourceInitializerInvokerTests { ...@@ -155,7 +158,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void initializationDoesNotApplyWithSeveralDataSources() { public void initializationDoesNotApplyWithSeveralDataSources() {
this.contextRunner.withUserConfiguration(TwoDataSources.class) this.contextRunner.withUserConfiguration(TwoDataSources.class)
.withPropertyValues("spring.datasource.initialize:true") .withPropertyValues("spring.datasource.initialization-mode:always")
.run((context) -> { .run((context) -> {
assertThat(context.getBeanNamesForType(DataSource.class)).hasSize(2); assertThat(context.getBeanNamesForType(DataSource.class)).hasSize(2);
assertDataSourceNotInitialized( assertDataSourceNotInitialized(
...@@ -190,7 +193,8 @@ public class DataSourceInitializerInvokerTests { ...@@ -190,7 +193,8 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithSchemaCredentials() { public void dataSourceInitializedWithSchemaCredentials() {
this.contextRunner.withPropertyValues("spring.datasource.initialize:true", this.contextRunner.withPropertyValues(
"spring.datasource.initialization-mode:always",
"spring.datasource.sqlScriptEncoding:UTF-8", "spring.datasource.sqlScriptEncoding:UTF-8",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("encoding-schema.sql"), + getRelativeLocationFor("encoding-schema.sql"),
...@@ -205,7 +209,8 @@ public class DataSourceInitializerInvokerTests { ...@@ -205,7 +209,8 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithDataCredentials() { public void dataSourceInitializedWithDataCredentials() {
this.contextRunner.withPropertyValues("spring.datasource.initialize:true", this.contextRunner.withPropertyValues(
"spring.datasource.initialization-mode:always",
"spring.datasource.sqlScriptEncoding:UTF-8", "spring.datasource.sqlScriptEncoding:UTF-8",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("encoding-schema.sql"), + getRelativeLocationFor("encoding-schema.sql"),
...@@ -226,10 +231,9 @@ public class DataSourceInitializerInvokerTests { ...@@ -226,10 +231,9 @@ public class DataSourceInitializerInvokerTests {
new ReverseOrderResourceLoader(new DefaultResourceLoader())); new ReverseOrderResourceLoader(new DefaultResourceLoader()));
return context; return context;
}).withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) }).withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialize=false", .withPropertyValues("spring.datasource.initialization-mode=always",
"spring.datasource.url:jdbc:hsqldb:mem:testdb-" "spring.datasource.url:jdbc:hsqldb:mem:testdb-"
+ new Random().nextInt(), + new Random().nextInt(),
"spring.datasource.initialize:true",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("lexical-schema-*.sql"), + getRelativeLocationFor("lexical-schema-*.sql"),
"spring.datasource.data:" + getRelativeLocationFor("data.sql")) "spring.datasource.data:" + getRelativeLocationFor("data.sql"))
...@@ -246,7 +250,7 @@ public class DataSourceInitializerInvokerTests { ...@@ -246,7 +250,7 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void testDataSourceInitializedWithInvalidSchemaResource() { public void testDataSourceInitializedWithInvalidSchemaResource() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.datasource.initialize:true", .withPropertyValues("spring.datasource.initialization-mode:always",
"spring.datasource.schema:classpath:does/not/exist.sql") "spring.datasource.schema:classpath:does/not/exist.sql")
.run((context) -> { .run((context) -> {
assertThat(context).hasFailed(); assertThat(context).hasFailed();
...@@ -262,7 +266,8 @@ public class DataSourceInitializerInvokerTests { ...@@ -262,7 +266,8 @@ public class DataSourceInitializerInvokerTests {
@Test @Test
public void dataSourceInitializedWithInvalidDataResource() { public void dataSourceInitializedWithInvalidDataResource() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.datasource.initialize:true", .withPropertyValues(
"spring.datasource.initialization-mode:always",
"spring.datasource.schema:" "spring.datasource.schema:"
+ getRelativeLocationFor("schema.sql"), + getRelativeLocationFor("schema.sql"),
"spring.datasource.data:classpath:does/not/exist.sql") "spring.datasource.data:classpath:does/not/exist.sql")
......
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.UUID;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.Test;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.jdbc.core.JdbcTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link DataSourceInitializer}.
*
* @author Stephane Nicoll
*/
public class DataSourceInitializerTests {
@Test
public void initializeEmbeddedByDefault() {
try (HikariDataSource dataSource = createDataSource()) {
DataSourceInitializer initializer = new DataSourceInitializer(
dataSource, new DataSourceProperties());
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
assertThat(initializer.createSchema()).isTrue();
assertNumberOfRows(jdbcTemplate, 0);
initializer.initSchema();
assertNumberOfRows(jdbcTemplate, 1);
}
}
@Test
public void initializeWithModeAlways() {
try (HikariDataSource dataSource = createDataSource()) {
DataSourceProperties properties = new DataSourceProperties();
properties.setInitializationMode(DataSourceInitializationMode.ALWAYS);
DataSourceInitializer initializer = new DataSourceInitializer(
dataSource, properties);
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
assertThat(initializer.createSchema()).isTrue();
assertNumberOfRows(jdbcTemplate, 0);
initializer.initSchema();
assertNumberOfRows(jdbcTemplate, 1);
}
}
private void assertNumberOfRows(JdbcTemplate jdbcTemplate, int count) {
assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) from BAR", Integer.class))
.isEqualTo(count);
}
@Test
public void initializeWithModeNever() {
try (HikariDataSource dataSource = createDataSource()) {
DataSourceProperties properties = new DataSourceProperties();
properties.setInitializationMode(DataSourceInitializationMode.NEVER);
DataSourceInitializer initializer = new DataSourceInitializer(
dataSource, properties);
assertThat(initializer.createSchema()).isFalse();
}
}
@Test
public void initializeOnlyEmbeddedByDefault() throws SQLException {
DatabaseMetaData metadata = mock(DatabaseMetaData.class);
given(metadata.getDatabaseProductName()).willReturn("MySQL");
Connection connection = mock(Connection.class);
given(connection.getMetaData()).willReturn(metadata);
DataSource dataSource = mock(DataSource.class);
given(dataSource.getConnection()).willReturn(connection);
DataSourceInitializer initializer = new DataSourceInitializer(
dataSource, new DataSourceProperties());
assertThat(initializer.createSchema()).isFalse();
verify(dataSource.getConnection());
}
private HikariDataSource createDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.url("jdbc:h2:mem:" + UUID.randomUUID().toString()).build();
}
}
...@@ -103,7 +103,8 @@ public class HikariDataSourceConfigurationTests { ...@@ -103,7 +103,8 @@ public class HikariDataSourceConfigurationTests {
private void load(String... environment) { private void load(String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
TestPropertyValues.of(environment).and("spring.datasource.initialize=false") TestPropertyValues.of(environment)
.and("spring.datasource.initialization-mode=never")
.and("spring.datasource.type=" + HikariDataSource.class.getName()) .and("spring.datasource.type=" + HikariDataSource.class.getName())
.applyTo(ctx); .applyTo(ctx);
ctx.register(DataSourceAutoConfiguration.class); ctx.register(DataSourceAutoConfiguration.class);
......
...@@ -63,7 +63,8 @@ public class HikariDriverConfigurationFailureAnalyzerTests { ...@@ -63,7 +63,8 @@ public class HikariDriverConfigurationFailureAnalyzerTests {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
TestPropertyValues TestPropertyValues
.of("spring.datasource.type=" + HikariDataSource.class.getName(), .of("spring.datasource.type=" + HikariDataSource.class.getName(),
"spring.datasource.hikari.data-source-class-name=com.example.Foo") "spring.datasource.hikari.data-source-class-name=com.example.Foo",
"spring.datasource.initialization-mode=always")
.applyTo(context); .applyTo(context);
context.register(configuration); context.register(configuration);
try { try {
......
...@@ -158,7 +158,7 @@ public class JdbcTemplateAutoConfigurationTests { ...@@ -158,7 +158,7 @@ public class JdbcTemplateAutoConfigurationTests {
public void load(Class<?> config, String... environment) { public void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialize:false", TestPropertyValues.of("spring.datasource.initialization-mode:never",
"spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()) "spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt())
.applyTo(ctx); .applyTo(ctx);
TestPropertyValues.of(environment).applyTo(ctx); TestPropertyValues.of(environment).applyTo(ctx);
......
...@@ -73,7 +73,7 @@ public class CustomHibernateJpaAutoConfigurationTests { ...@@ -73,7 +73,7 @@ public class CustomHibernateJpaAutoConfigurationTests {
@Test @Test
public void defaultDatabaseForH2() { public void defaultDatabaseForH2() {
this.contextRunner.withPropertyValues("spring.datasource.url:jdbc:h2:mem:testdb", this.contextRunner.withPropertyValues("spring.datasource.url:jdbc:h2:mem:testdb",
"spring.datasource.initialize:false").run((context) -> { "spring.datasource.initialization-mode:never").run((context) -> {
HibernateJpaVendorAdapter bean = context HibernateJpaVendorAdapter bean = context
.getBean(HibernateJpaVendorAdapter.class); .getBean(HibernateJpaVendorAdapter.class);
Database database = (Database) ReflectionTestUtils.getField(bean, Database database = (Database) ReflectionTestUtils.getField(bean,
......
...@@ -42,7 +42,7 @@ public class HibernateDefaultDdlAutoProviderTests { ...@@ -42,7 +42,7 @@ public class HibernateDefaultDdlAutoProviderTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class)) HibernateJpaAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialize:false"); .withPropertyValues("spring.datasource.initialization-mode:never");
@Test @Test
public void defaultDdlAutoForMysql() { public void defaultDdlAutoForMysql() {
......
...@@ -114,7 +114,7 @@ public class HibernateJpaAutoConfigurationTests ...@@ -114,7 +114,7 @@ public class HibernateJpaAutoConfigurationTests
@Test @Test
public void testFlywaySwitchOffDdlAuto() { public void testFlywaySwitchOffDdlAuto() {
contextRunner() contextRunner()
.withPropertyValues("spring.datasource.initialize:false", .withPropertyValues("spring.datasource.initialization-mode:never",
"spring.flyway.locations:classpath:db/city") "spring.flyway.locations:classpath:db/city")
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.run((context) -> assertThat(context).hasNotFailed()); .run((context) -> assertThat(context).hasNotFailed());
...@@ -123,7 +123,7 @@ public class HibernateJpaAutoConfigurationTests ...@@ -123,7 +123,7 @@ public class HibernateJpaAutoConfigurationTests
@Test @Test
public void testFlywayPlusValidation() { public void testFlywayPlusValidation() {
contextRunner() contextRunner()
.withPropertyValues("spring.datasource.initialize:false", .withPropertyValues("spring.datasource.initialization-mode:never",
"spring.flyway.locations:classpath:db/city", "spring.flyway.locations:classpath:db/city",
"spring.jpa.hibernate.ddl-auto:validate") "spring.jpa.hibernate.ddl-auto:validate")
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
...@@ -133,7 +133,7 @@ public class HibernateJpaAutoConfigurationTests ...@@ -133,7 +133,7 @@ public class HibernateJpaAutoConfigurationTests
@Test @Test
public void testLiquibasePlusValidation() { public void testLiquibasePlusValidation() {
contextRunner() contextRunner()
.withPropertyValues("spring.datasource.initialize:false", .withPropertyValues("spring.datasource.initialization-mode:never",
"spring.liquibase.changeLog:classpath:db/changelog/db.changelog-city.yaml", "spring.liquibase.changeLog:classpath:db/changelog/db.changelog-city.yaml",
"spring.jpa.hibernate.ddl-auto:validate") "spring.jpa.hibernate.ddl-auto:validate")
.withConfiguration( .withConfiguration(
......
...@@ -209,7 +209,7 @@ public class SecurityAutoConfigurationTests { ...@@ -209,7 +209,7 @@ public class SecurityAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
TestPropertyValues.of("spring.datasource.url:jdbc:hsqldb:mem:testsecdb", TestPropertyValues.of("spring.datasource.url:jdbc:hsqldb:mem:testsecdb",
"spring.datasource.initialize:false").applyTo(this.context); "spring.datasource.initialization-mode:never").applyTo(this.context);
this.context.register(EntityConfiguration.class, this.context.register(EntityConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
......
...@@ -70,7 +70,7 @@ public class TransactionAutoConfigurationTests { ...@@ -70,7 +70,7 @@ public class TransactionAutoConfigurationTests {
public void singleTransactionManager() { public void singleTransactionManager() {
load(new Class<?>[] { DataSourceAutoConfiguration.class, load(new Class<?>[] { DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class }, DataSourceTransactionManagerAutoConfiguration.class },
"spring.datasource.initialize:false"); "spring.datasource.initialization-mode:never");
PlatformTransactionManager transactionManager = this.context PlatformTransactionManager transactionManager = this.context
.getBean(PlatformTransactionManager.class); .getBean(PlatformTransactionManager.class);
TransactionTemplate transactionTemplate = this.context TransactionTemplate transactionTemplate = this.context
......
...@@ -658,7 +658,7 @@ content into your application; rather pick only the properties that you need. ...@@ -658,7 +658,7 @@ content into your application; rather pick only the properties that you need.
spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
spring.datasource.generate-unique-name=false # Generate a random datasource name. spring.datasource.generate-unique-name=false # Generate a random datasource name.
spring.datasource.hikari.*= # Hikari specific settings spring.datasource.hikari.*= # Hikari specific settings
spring.datasource.initialize=true # Populate the database using 'data.sql'. spring.datasource.initialization-mode=embedded # Initialize the datasource using available DDL and DML scripts.
spring.datasource.jmx-enabled=false # Enable JMX support (if provided by the underlying pool). spring.datasource.jmx-enabled=false # Enable JMX support (if provided by the underlying pool).
spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set. spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set.
spring.datasource.name=testdb # Name of the datasource. spring.datasource.name=testdb # Name of the datasource.
......
...@@ -1921,6 +1921,10 @@ is the value of `spring.datasource.platform`. This allows you to switch to datab ...@@ -1921,6 +1921,10 @@ is the value of `spring.datasource.platform`. This allows you to switch to datab
specific scripts if necessary, e.g. you might choose to set it to the vendor name of the specific scripts if necessary, e.g. you might choose to set it to the vendor name of the
database (`hsqldb`, `h2`, `oracle`, `mysql`, `postgresql` etc.). database (`hsqldb`, `h2`, `oracle`, `mysql`, `postgresql` etc.).
Spring Boot automatically creates the schema of an embedded `DataSource`. This behavior
can be customized using the `spring.datasource.initialization-mode` property (can also be
`always` or `never`).
Spring Boot enables the fail-fast feature of the Spring JDBC initializer by default, so if Spring Boot enables the fail-fast feature of the Spring JDBC initializer by default, so if
the scripts cause exceptions the application will fail to start. You can tune that using the scripts cause exceptions the application will fail to start. You can tune that using
`spring.datasource.continue-on-error`. `spring.datasource.continue-on-error`.
...@@ -1929,8 +1933,6 @@ NOTE: In a JPA-based app, you can choose to let Hibernate create the schema or u ...@@ -1929,8 +1933,6 @@ NOTE: In a JPA-based app, you can choose to let Hibernate create the schema or u
`schema.sql` but not both. Make sure to disable `spring.jpa.hibernate.ddl-auto` if you `schema.sql` but not both. Make sure to disable `spring.jpa.hibernate.ddl-auto` if you
chose the later. chose the later.
You can also disable initialization by setting `spring.datasource.initialize` to `false`.
[[howto-initialize-a-spring-batch-database]] [[howto-initialize-a-spring-batch-database]]
......
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