多飞路与 FlywayMigrationStrategy
Multiple Flyways with FlywayMigrationStrategy
我有多个 Flyway
数据源,需要对它们实施 FlywayMigrationStrategy
。每个数据源都有自己的 flyway_migration
table 等
但是当我创建时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)
这意味着如果 class Flyway.class
的 bean 已经存在于 spring 上下文中,则不会创建配置。 ok,接下来,配置只创建到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
,这会启动迁移。如您所见,FlywayMigrationStrategy
被设置为 FlywayMigrationInitializer
作为构造函数参数。如果设置了MigrationStrategy,就是他使用,否则就执行flyway.migrate()
。 (查看源代码)
好的,现在我们知道它的一般工作原理了,让我们看看您的代码。
您在主配置中创建飞行路线实例:
@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 实例执行两次:作为 bean initMethod
和来自 Testconfiguration postcontruct 方法。我不确定这是不是你想要的。
好的,为了修复它,我建议删除 (initMethod = "migrate")
和 @FlywayDataSource
,在主配置中为每个 Flyway
bean 创建 FlywayMigrationInitializer
bean 并实现 FlywayMigrationStrategy
在你的测试配置中。
@Bean
public FlywayMigrationInitializer flywayInitializer(@Qualifier(...) Flyway flyway,
ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
return new FlywayMigrationInitializer(flyway, migrationStrategy.getIfAvailable());
}
我有多个 Flyway
数据源,需要对它们实施 FlywayMigrationStrategy
。每个数据源都有自己的 flyway_migration
table 等
但是当我创建时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)
这意味着如果 class Flyway.class
的 bean 已经存在于 spring 上下文中,则不会创建配置。 ok,接下来,配置只创建到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
,这会启动迁移。如您所见,FlywayMigrationStrategy
被设置为 FlywayMigrationInitializer
作为构造函数参数。如果设置了MigrationStrategy,就是他使用,否则就执行flyway.migrate()
。 (查看源代码)
好的,现在我们知道它的一般工作原理了,让我们看看您的代码。
您在主配置中创建飞行路线实例:
@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 实例执行两次:作为 bean initMethod
和来自 Testconfiguration postcontruct 方法。我不确定这是不是你想要的。
好的,为了修复它,我建议删除 (initMethod = "migrate")
和 @FlywayDataSource
,在主配置中为每个 Flyway
bean 创建 FlywayMigrationInitializer
bean 并实现 FlywayMigrationStrategy
在你的测试配置中。
@Bean
public FlywayMigrationInitializer flywayInitializer(@Qualifier(...) Flyway flyway,
ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
return new FlywayMigrationInitializer(flyway, migrationStrategy.getIfAvailable());
}