spring-boot - 使用 FlywayMigrationStrategy 的多个 Flyway
问题描述
我有多个Flyway
数据源,需要对FlywayMigrationStrategy
它们实施。每个数据源都有自己的flyway_migration
表等。
但是当我创建FlywayMigrationStrategy
它时不会被调用。
这不起作用:
@Bean
public FlywayMigrationStrategy cleanMigrateStrategy() { ...
这有效:
@PostConstruct
public void cleanBeforeMigrate(
@Qualifier("dpaFlyway") Flyway dpaflyway,
@Qualifier("flyway") Flyway flyway) {
dpaflyway.clean();
dpaflyway.migrate();
flyway.clean();
flyway.migrate();
}
有更好的选择吗?
解决方案
为什么要实现@PostContruct
方法?如我所见,FlywayMigrationStrategy
是一个功能接口,我猜您的代码应该如下所示:
@Bean
public FlywayMigrationStrategy cleanMigrateStrategy() {
FlywayMigrationStrategy strategy = new FlywayMigrationStrategy() {
@Override
public void migrate(Flyway flyway) {
flyway.clean();
flyway.migrate();
}
};
return strategy;
}
好的,我有一些研究,现在可以解释你的问题的答案。
首先,让我们检查一下FlywayAutoConfiguration
当您使用通过属性文件配置 flyway 迁移时,配置工作,创建和配置 Flyway 实例并迁移基础。所有这些都配置在FlywayConfiguration
. 再来看看配置上的条件注解
@ConditionalOnMissingBean(Flyway.class)
这意味着如果类的 beanFlyway.class
已经存在于 spring 上下文中,则不会创建配置。好的,接下来,配置只创建到bean
@Bean
public Flyway flyway(FlywayProperties properties, DataSourceProperties dataSourceProperties,
ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
@FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks)
.....
@Bean
@ConditionalOnMissingBean
public FlywayMigrationInitializer flywayInitializer(Flyway flyway,
ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
return new FlywayMigrationInitializer(flyway, migrationStrategy.getIfAvailable());
}
配置如何配置flyway
bean 并不重要,但重要的是它创建了FlywayMigrationInitializer
启动迁移的 bean。如您所见,FlywayMigrationStrategy
设置FlywayMigrationInitializer
为构造函数参数。如果设置了 MigrationStrategy ,则由他使用,否则只需执行flyway.migrate()
。(见源代码)
好的,现在我们知道它一般是如何工作的,让我们看看你的代码。
您在主配置中创建 flyway 实例:
@Bean(initMethod = "migrate")
@FlywayDataSource
public Flyway firstFlyway(DataSource dataSource) {
return new Flyway(
new FluentConfiguration()
.locations("db/first-migration")
.schemas("first")
.outOfOrder(true)
.dataSource(dataSource)
);
}
@Bean(initMethod = "migrate")
@FlywayDataSource
public Flyway secondFlyway(@Qualifier("secondDataSource") DataSource dataSource) {
return new Flyway(
new FluentConfiguration()
.dataSource(dataSource)
.schemas("second")
.outOfOrder(true)
.locations("db/second-migration")
);
}
由于您已经创建了 Flyway 实例,FlywayConfiguration
因此不会创建(由于条件)并且Flyway
也不会创建您的 bean 的 Initializer bean。因此迁移不会执行,您需要添加(initMethod = "migrate")
到 bean 声明以开始迁移。另外,我认为这@FlywayDataSource
不是必需的,什么也不做。
现在让我们转到您的测试配置。
创建时FlywayMigrationStrategy
,它可以正常工作,但没有人使用该策略(在您的主配置文件中,您调用的Flyway.migrate
只是 initMethod 和 MigrationInitializer 未创建)。结果,该策略没有被执行。
TestConfiguration
在您的工作示例中,您在postconstruct 方法中添加了调用 clean 和 migrate 。它之所以有效,是因为 postconstruct 方法是在创建配置后执行的。但是,如果您调试代码,您将看到该migrate
方法为每个 Flyway 实例执行两次:作为 beaninitMethod
和来自 Testconfiguration postcontruct 方法。我不确定这是你想要的。
好的,为了修复它,我建议删除(initMethod = "migrate")
and ,为您的主配置中的每个bean@FlywayDataSource
创建bean 并在您的测试配置中实现。FlywayMigrationInitializer
Flyway
FlywayMigrationStrategy
@Bean
public FlywayMigrationInitializer flywayInitializer(@Qualifier(...) Flyway flyway,
ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
return new FlywayMigrationInitializer(flyway, migrationStrategy.getIfAvailable());
}
推荐阅读
- angular - 读取 AppModule 中的 localStorage 数据
- php - 运行测试 Yii2 Codeception 后如何恢复数据库更改
- perl - 根据一行中的条件从多个文件中提取行
- java - 如何在一个应用程序中处理基于表单的身份验证和基于 (jwt) 令牌的身份验证
- javascript - Codepen 中的 SemanticUI 示例不起作用
- mysql - 在内部联接上访问左联接
- c# - C# 组合框选定项更改(从单击选项到底部选项)
- ios - iOS 自定义初始化问题,如何设置默认初始化方法?
- java - LocalDate 返回随机日期
- java - Spring Rest Template Http 客户端错误异常