Spring 和 Flyway - 在应用程序上下文启动之前迁移

Posted

技术标签:

【中文标题】Spring 和 Flyway - 在应用程序上下文启动之前迁移【英文标题】:Spring and Flyway - migrate before application context starts up 【发布时间】:2021-04-20 13:24:06 【问题描述】:

正如标题所示,我正在寻找可以帮助我在加载 Springs 应用程序上下文(准确地说是持久性上下文)之前运行 Flyway 迁移的任何方法。原因是我在应用程序启动时运行的查询很少。这导致我的测试失败,因为正在对尚不存在的数据库表执行查询。我使用 H2 作为我的测试数据库。现在我只使用flyway核心依赖:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>6.5.0</version>
    <scope>test</scope>
</dependency>

我有一个如下的 Flyway 配置类:

@Configuration
class FlywayConfig 

    private static final String resourcePath = "classpath:flyway/migrations";
    private static final String sampleDataPath = "classpath:flyway/sample_data";

    @Bean
    Flyway flyway(@Value("$spring.datasource.url") String dataSource,
                  @Value("$spring.datasource.username") String username,
                  @Value("$spring.datasource.password") String password) 


        FluentConfiguration fluentConfiguration = Flyway.configure().dataSource(dataSource, username, password);

        fluentConfiguration.locations(resourcePath, sampleDataPath);

        Flyway flyway = fluentConfiguration.load();

        return flyway;
    

并且属性定义在application.yml

spring:
  datasource:
    username: sa
    password: sa
    url: 'jdbc:h2:mem:testdb;Mode=Oracle;IGNORE_CATALOGS=TRUE;DB_CLOSE_DELAY=-1;'
    platform: h2
  h2:
    console:
      enabled: true
  jpa:
    show-sql: true

我想要实现的是:1. flyway 进行迁移 2. Spring 上下文加载(按特定顺序)

【问题讨论】:

【参考方案1】:

我设法通过在配置文件中手动创建 DataSource 对象(不是由 Spring 从 application.yml 自动创建)并在 DataSource 对象上使用 @DependsOn 来完成我想要的。通过这种方式,我确保一旦我在Flyway bean 中进行迁移(顺便说一句,我也对其进行了调整),将建立来自应用程序上下文的任何可能的数据库连接。我在测试之前正在清理和迁移 Flyway,现在我必须在初始化应用程序上下文 bean 时这样做。这是对我有用的代码:

@Configuration
class DatabaseConfig 

    private static final String resourcePath = "classpath:flyway/migrations";
    private static final String sampleDataPath = "classpath:flyway/sample_data";

    private static final String dataSourceUrl = "jdbc:h2:mem:testdb;Mode=Oracle;IGNORE_CATALOGS=TRUE;DB_CLOSE_DELAY=-1;";
    private static final String username = "sa";
    private static final String password = "sa";

    @Bean("flyway")
    public Flyway flyway() 

        FluentConfiguration fluentConfiguration = Flyway.configure().dataSource(dataSourceUrl, username, password);

        fluentConfiguration.locations(resourcePath, sampleDataPath);

        Flyway flyway = fluentConfiguration.load();

        flyway.clean();
        flyway.migrate();

        return flyway;
    

    @DependsOn("flyway")
    @Bean
    public DataSource dataSource() 
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName("org.h2.Driver");
        dataSourceBuilder.url(dataSourceUrl);
        dataSourceBuilder.username(username);
        dataSourceBuilder.password(password);
        return dataSourceBuilder.build();
    

这里是application.yml 文件(我去掉了与数据源相关的记录):

spring:
  h2:
    console:
      enabled: true
  jpa:
    show-sql: true

flyway:
  enabled: false

【讨论】:

以上是关于Spring 和 Flyway - 在应用程序上下文启动之前迁移的主要内容,如果未能解决你的问题,请参考以下文章

Flyway、Spring Boot 和应用程序在没有数据库的情况下启动

如何一起使用Spring启动,JOOQ和Flyway?

Spring boot、JOOQ和Flyway如何一起使用?

使用 Flyway 和 Spring Boot 在 docker testcontainers 环境中迁移模式

Flyway 在 Spring Boot 上不工作时如何调试?

Flyway 迁移在 MS SQL Server 中成功,但在 H2 数据库中失败