在 Spring Boot 应用程序中使用 Flyway 进行多数据源迁移
Multiple datasources migrations using Flyway in a Spring Boot application
我们在 Spring 基于引导的应用程序中使用 Flyway 进行数据库迁移,现在我们需要在使用多数据源策略时引入多租户支持。作为其中的一部分,我们还需要支持多个数据源的迁移。所有数据源都应保持相同的结构,因此应使用相同的迁移脚本来迁移所有数据源。此外,迁移应该在应用程序启动时发生(与构建时间相反,而 maven 插件似乎可以配置为迁移多个数据源)。实现这一目标的最佳方法是什么?该应用程序已经定义了数据源 bean,但 Flyway 仅对主数据源执行迁移。
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();
让@Roger Thomas 回答更多 Spring 引导方式:
最简单的解决方案是用 @Primary
注释您的主数据源(您已经这样做了),然后让 bootstrap 以 'normal' 方式迁移您的主数据源。
对于其他数据源,手动迁移这些数据源:
@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();
}
}
遇到了同样的问题...我在 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>
}
为此找到了一个简单的解决方案 - 我在创建 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/...
这对我有用。
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
我们在 Spring 基于引导的应用程序中使用 Flyway 进行数据库迁移,现在我们需要在使用多数据源策略时引入多租户支持。作为其中的一部分,我们还需要支持多个数据源的迁移。所有数据源都应保持相同的结构,因此应使用相同的迁移脚本来迁移所有数据源。此外,迁移应该在应用程序启动时发生(与构建时间相反,而 maven 插件似乎可以配置为迁移多个数据源)。实现这一目标的最佳方法是什么?该应用程序已经定义了数据源 bean,但 Flyway 仅对主数据源执行迁移。
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();
让@Roger Thomas 回答更多 Spring 引导方式:
最简单的解决方案是用 @Primary
注释您的主数据源(您已经这样做了),然后让 bootstrap 以 'normal' 方式迁移您的主数据源。
对于其他数据源,手动迁移这些数据源:
@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();
}
}
遇到了同样的问题...我在 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>
}
为此找到了一个简单的解决方案 - 我在创建 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/...
这对我有用。
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