diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java index 0b5f64f9a6e..c49ea59ebbf 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java @@ -82,8 +82,6 @@ public class FlywayAutoConfiguration { @EnableConfigurationProperties(FlywayProperties.class) public static class FlywayConfiguration { - private static final String VENDOR_PLACEHOLDER = "{vendor}"; - private final FlywayProperties properties; private final ResourceLoader resourceLoader; @@ -131,31 +129,7 @@ public class FlywayAutoConfiguration { @Bean @ConfigurationProperties(prefix = "flyway") public Flyway flyway() { - Flyway flyway = new Flyway() { - - @Override - public void setLocations(String... locations) { - if (usesVendorLocation()) { - try { - String url = (String) JdbcUtils.extractDatabaseMetaData( - getDataSource(), "getURL"); - DatabaseDriver vendor = DatabaseDriver.fromJdbcUrl(url); - if (vendor != DatabaseDriver.UNKNOWN) { - for (int i = 0; i < locations.length; i++) { - locations[i] = locations[i].replace( - VENDOR_PLACEHOLDER, - vendor.name().toLowerCase()); - } - } - } - catch (MetaDataAccessException e) { - throw new IllegalStateException(e); - } - } - super.setLocations(locations); - } - - }; + Flyway flyway = new SpringBootFlyway(); if (this.properties.isCreateDataSource()) { flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(), this.properties.getPassword(), @@ -171,15 +145,6 @@ public class FlywayAutoConfiguration { return flyway; } - private boolean usesVendorLocation() { - for (String location : this.properties.getLocations()) { - if (location.contains(VENDOR_PLACEHOLDER)) { - return true; - } - } - return false; - } - @Bean @ConditionalOnMissingBean public FlywayMigrationInitializer flywayInitializer(Flyway flyway) { @@ -220,6 +185,45 @@ public class FlywayAutoConfiguration { } + + private static class SpringBootFlyway extends Flyway { + + private static final String VENDOR_PLACEHOLDER = "{vendor}"; + + @Override + public void setLocations(String... locations) { + if (usesVendorLocation(locations)) { + try { + String url = (String) JdbcUtils.extractDatabaseMetaData( + getDataSource(), "getURL"); + DatabaseDriver vendor = DatabaseDriver.fromJdbcUrl(url); + if (vendor != DatabaseDriver.UNKNOWN) { + for (int i = 0; i < locations.length; i++) { + locations[i] = locations[i].replace( + VENDOR_PLACEHOLDER, + vendor.getId()); + } + } + } + catch (MetaDataAccessException ex) { + throw new IllegalStateException(ex); + } + } + super.setLocations(locations); + } + + + private boolean usesVendorLocation(String... locations) { + for (String location : locations) { + if (location.contains(VENDOR_PLACEHOLDER)) { + return true; + } + } + return false; + } + + } + /** * Convert a String or Number to a {@link MigrationVersion}. */ diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java index f63a4f6b714..d503f79e057 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayProperties.java @@ -17,7 +17,6 @@ package org.springframework.boot.autoconfigure.flyway; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -38,9 +37,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties; public class FlywayProperties { /** - * Locations of migrations scripts. + * Locations of migrations scripts. Can contain the special "{vendor}" placeholder + * to use vendor-specific locations. */ - private List locations = new ArrayList(Arrays.asList("db/migration")); + private List locations = new ArrayList(Collections.singletonList("db/migration")); /** * Check that migration scripts location exists. diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index 196ff1e2863..aeca7652c00 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -237,19 +237,18 @@ public class FlywayAutoConfigurationTests { @Test public void useVendorDirectory() throws Exception { EnvironmentTestUtils.addEnvironment(this.context, - "flyway.locations:classpath:db/vendors/{vendor}"); + "flyway.locations=classpath:db/vendors/{vendor},classpath:db/changelog"); registerAndRefresh(EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); Flyway flyway = this.context.getBean(Flyway.class); - assertThat(flyway.getLocations()).containsExactly( - "classpath:db/vendors/h2"); + assertThat(flyway.getLocations()).containsExactlyInAnyOrder( + "classpath:db/vendors/h2", "classpath:db/changelog"); } private void registerAndRefresh(Class... annotatedClasses) { this.context.register(annotatedClasses); this.context.refresh(); - } @Configuration diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index c29bae81fea..091ae66d80c 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -2062,9 +2062,20 @@ To automatically run Flyway database migrations on startup, add the The migrations are scripts in the form `V__.sql` (with `` an underscore-separated version, e.g. '`1`' or '`2_1`'). By default they live in a folder -`classpath:db/migration` but you can modify that using `flyway.locations` (a list). See -the Flyway class from flyway-core for details of available settings like schemas etc. In -addition Spring Boot provides a small set of properties in +`classpath:db/migration` but you can modify that using `flyway.locations`. You can also +add a special `{vendor}` placeholder to use vendor-specific scripts. Assume the following: + +[source,properties,indent=0] +---- + flyway.locations=db/migration/{vendor} +---- + +Rather than using `db/migration`, this configuration will set the folder to use according +to the type of the database (i.e. `db/migration/mysql` for MySql). The list of supported +database are available in {sc-spring-boot}/jdbc/DatabaseDriver.{sc-ext}[`DatabaseDriver`]. + +See also the Flyway class from flyway-core for details of available settings like schemas +etc. In addition Spring Boot provides a small set of properties in {sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[`FlywayProperties`] that can be used to disable the migrations, or switch off the location checking. Spring Boot will call `Flyway.migrate()` to perform the database migration. If you would like diff --git a/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java b/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java index 27bd772fef1..22522b794ae 100644 --- a/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java +++ b/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java @@ -182,13 +182,13 @@ public enum DatabaseDriver { private final String validationQuery; - DatabaseDriver(String id, String name, String driverClassName) { - this(id, name, driverClassName, null); + DatabaseDriver(String id, String productName, String driverClassName) { + this(id, productName, driverClassName, null); } - DatabaseDriver(String id, String name, String driverClassName, + DatabaseDriver(String id, String productName, String driverClassName, String xaDataSourceClassName) { - this(id, name, driverClassName, xaDataSourceClassName, null); + this(id, productName, driverClassName, xaDataSourceClassName, null); } DatabaseDriver(String id, String productName, String driverClassName,