Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FlyWay + Spring Boot 2.x for vendor specific scripts error: found more than one migration with version 1.x

I'm trying to configure FlyWay to work with two vendors - one (H2) is for local environment, and another one (Mysql) is for ci.

Here's my scripts patch:

patch

My FlyWay bean configuration:

@Bean(initMethod = "migrate")
    Flyway flyway() {
        Flyway flyway = Flyway
                .configure()
                .dataSource(dataSource(dataSourceProperties()))
                .locations("classpath:db/migration/MySQL", "classpath:db/migration/H2")
                .load();
        return flyway;
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("spring.datasource")
    public HikariDataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
                .build();
    }

And my application.yml configuration:

spring:
  main:
    allow-bean-definition-overriding: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbc-url: jdbc:mysql://localhost:3306/messages
    username: username
    password: password

What I try to achieve is to make flyway run database vendor specific scripts, depending on which database is set in datasource. Here's what I get:

Caused by: org.flywaydb.core.api.FlywayException: Found more than one migration with version 1.1
Offenders:
-> C:\Projects\my-project\out\production\resources\db\specific\MySQL\V1_1__Create_table_message.sql (SQL)
-> C:\Projects\my-project\out\production\resources\db\specific\H2\V1_1__Create_table_message.sql (SQL)

I've already tried to use lowercase vendor names (db/migration/mysql ...) and use db/specific/ instead of db/migration. Nothing worked for me.

like image 557
RichardK Avatar asked Jan 31 '19 12:01

RichardK


1 Answers

The problem is your use of:

.locations("classpath:db/migration/MySQL", "classpath:db/migration/H2")

This will add both migrations to the runtime path. This is what causes the issue, because this configuration instructs flyway to always use the scripts from both locations, instead of only using the H2-scripts for H2 and the MySQL scripts for MySQL.

Instead, you should only add the specific path for the active driver on the path.

Something like

String driverVendor = ..; // something to decide h2 or mysql
Flyway flyway = Flyway
        .configure()
        .locations("classpath:db/migration/" + driverVendor)

You may need to lowercase the folder names, that is H2 to h2 and MySQL to mysql for this to work.

Alternatively, consider using Spring Boots Flyway auto-configuration instead of coding the Flyway configuration in code. This allows you to define the path in the application config as:

spring.flyway.locations=classpath:db/migration/{vendor}

Where {vendor} will be automatically populated with the vendor name of the driver used to connect.

See also Execute Flyway Database Migrations on Startup

like image 51
Mark Rotteveel Avatar answered Oct 19 '22 19:10

Mark Rotteveel