【问题标题】:Multiple datasources migrations using Flyway in a Spring Boot application在 Spring Boot 应用程序中使用 Flyway 进行多数据源迁移
【发布时间】:2016-09-13 20:31:16
【问题描述】:

我们在基于 Spring Boot 的应用程序中使用 Flyway 进行数据库迁移,现在我们需要在使用多数据源策略时引入多租户支持。作为其中的一部分,我们还需要支持多个数据源的迁移。所有数据源都应保持相同的结构,因此应使用相同的迁移脚本来迁移所有数据源。此外,迁移应该在应用程序启动时发生(与构建时间相反,而 maven 插件似乎可以配置为迁移多个数据源)。为了实现这一目标,最好的方法是什么?该应用程序已经定义了数据源 bean,但 Flyway 仅对主数据源执行迁移。

【问题讨论】:

    标签: spring-boot flyway


    【解决方案1】:

    让@Roger Thomas 以 Spring Boot 方式回答更多问题:

    最简单的解决方案是使用 @Primary 注释您的主数据源(您已经这样做了),然后让引导程序以“正常”方式迁移您的主数据源。

    对于其他数据源,手动迁移这些数据源:

    @Configuration
    public class FlywaySlaveInitializer {
    
         @Autowired private DataSource dataSource2;
         @Autowired private DataSource dataSource3;
         //other datasources
    
         @PostConstruct
         public void migrateFlyway() {
             Flyway flyway = new Flyway();
             //if default config is not sufficient, call setters here
    
             //source 2
             flyway.setDataSource(dataSource2);
             flyway.setLocations("db/migration_source_2");
             flyway.migrate();
    
             //source 3
             flyway.setDataSource(dataSource3);
             flyway.setLocations("db/migration_source_3");
             flyway.migrate();
         }
    }
    

    【讨论】:

    • 第二个数据库的 sql 文件应该放在哪里?它们将如何区分?
    • 确保设置flyway.setBaselineOnMigrate(true)。这使 flyway 可以为迁移脚本设置其版本跟踪表。
    【解决方案2】:

    Flyway 支持使用 Java 编码的迁移,因此您可以在应用程序启动期间启动 Flyway。

    https://flywaydb.org/documentation/migration/java
    

    我不确定您将如何配置 Flyway 以通过其配置文件定位多个数据源。我自己的开发基于使用 Java 为我需要处理的每个数据源调用一次 Flyway。 Spring Boot 支持标记为 @FlywayDataSource 的 bean 的自动装配,但我还没有研究如何使用它。

    对于 in-java 解决方案,代码可以很简单

        Flyway flyway = new Flyway();
    
        // Set the data source
        flyway.setDataSource(dataSource);
    
        // Where to search for classes to be executed or SQL scripts to be found
        flyway.setLocations("net.somewhere.flyway");
    
        flyway.setTarget(MigrationVersion.LATEST);
        flyway.migrate();
    

    【讨论】:

    • Spring Boot 依赖于一系列自适应的自动配置类来创建和配置 bean 并在启动期间运行方法。 flyway 一可以在 {org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration} 找到,所以你基本上可以从这个类中复制你需要的代码。我正要尝试同样的事情。
    • Flyway 改变了创建 Flyway 对象的方式:Flyway flyway = Flyway.configure() .dataSource(dataSource).target(MigrationVersion.LATEST).load();
    【解决方案3】:

    遇到同样的问题...我查看了 org.springframework.boot.autoconfigure.flyway 包中 V 2.2.4 的 spring-boot-autoconfigure 工件,发现了一个注释 FlywayDataSource

    注释您希望 Flyway 使用的任何数据源都可以解决问题。
    像这样的:

    @FlywayDataSource
    @Bean(name = "someDatasource")
    public DataSource someDatasource(...) {
            <build and return your datasource>
    }
    

    【讨论】:

    • 似乎也支持多个数据源,请参阅renewinkler.net/2018/03/04/…
    • @JacobvanLingen 是的,这是我回答中大写“ANY”的目标。 :) 谢谢你的链接,在这种情况下——如果我理解正确的话——他正在使用注释将 Flyway 指向远离主数据源。有趣的使用!他正在定义 Flyway 使用的不同数据源,具有不同的前缀。 flyway DS 可能只是同一 DB 上的不同用户(因为来自主 DS 的用户无法执行迁移)或完全不同的 DB 来跟踪迁移完成了什么。
    【解决方案4】:

    为此找到了一个简单的解决方案 - 我在创建 emf 期间添加了该步骤:

    @Qualifier(EMF2)
    @Bean(name = EMF2)
    public LocalContainerEntityManagerFactoryBean entityManagerFactory2(
        final EntityManagerFactoryBuilder builder
    ) {
        final DataSource dataSource = dataSource2();
        Flyway.configure()
              .dataSource(dataSource)
              .locations("db/migration/ds2")
              .load()
              .migrate();
        return builder
            .dataSource(dataSource)
            .packages(Role.class)
            .properties(jpaProperties2().getProperties())
            .persistenceUnit("domain2")
            .build();
    }
    

    我为此禁用了 spring.flyway.enabled。

    SQL 文件位于 resources/db/migration/ds1/... 和 resources/db/migration/ds2/...

    【讨论】:

      【解决方案5】:

      这对我有用。

      import javax.annotation.PostConstruct;
      import org.flywaydb.core.Flyway;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class FlywaySlaveInitializer {
      
        @Value("${firstDatasource.db.url}")
        String firstDatasourceUrl;
        @Value("${firstDatasource.db.user}")
        String firstDatasourceUser;
        @Value("${firstDatasource.db.password}")
        String firstDatasourcePassword;
      
        @Value("${secondDatasource.db.url}")
        String secondDatasourceUrl;
        @Value("${secondDatasource.db.user}")
        String secondDatasourceUser;
        @Value("${secondDatasource.db.password}")
        String secondDatasourcePassword;
      
      
        @PostConstruct
        public void migrateFlyway() {
          Flyway flywayIntegration = Flyway.configure()
              .dataSource(firstDatasourceUrl, firstDatasourceUser, firstDatasourcePassword)
              .locations("filesystem:./src/main/resources/migration.first")
              .load();
      
          Flyway flywayPhenom = Flyway.configure()
              .dataSource(secondDatasourceUrl, secondDatasourceUser, secondDatasourcePassword)
              .locations("filesystem:./src/main/resources/migration.second")
              .load();
      
          flywayIntegration.migrate();
          flywayPhenom.migrate();
        }
      
      }
      
      

      在我的 application.yml 中这个属性:

      spring:
        flyway:
          enabled: false
      

      【讨论】:

        猜你喜欢
        • 2020-08-20
        • 2016-10-22
        • 2012-04-30
        • 2020-08-20
        • 1970-01-01
        • 1970-01-01
        • 2021-09-22
        • 2020-02-23
        • 2019-08-07
        相关资源
        最近更新 更多