具有Spring Boot和多个模式的Liquibase,如何指定执行顺序

时间:2019-02-11 16:41:12

标签: java spring-boot liquibase

我们有一个数据迁移作业,需要按此顺序初始化模式AB。我们通过定义多个SpringLiquibase处理多个模式,每个模式一个,每个都有自己的数据源和自己的主变更集。 (请注意,通常在Spring Boot中,您不需要定义SpringLiquibase,因为它将检测到一个数据源并使用该数据源为您自动配置SpringLiquibase。)

执行顺序似乎有所不同,具体取决于作业是在IDE中本地运行还是作为单个JAR Spring Boot应用程序捆绑在一起。

我们如何确保liquibase的两次执行按我们想要的顺序进行?

(为什么顺序很重要:A包含一些表,而B包含引用A中的表的视图。我们必须确保在grant select on A.* to B之前尝试create view B.some_view (...) as select ... from A.xyz,否则由于特权不足而无法创建B。)

2 个答案:

答案 0 :(得分:3)

经过一番摸索并深入研究了源代码,事实证明它非常简单。

SpringLiquibase实现InitializingBean,并在InitializingBean.afterPropertiesSet()方法内执行Liquibase更新。

在完成每个bean的初始化之后,Spring在每个bean上一个接一个地调用此方法。

因此,要强制执行特定顺序,您需要强制在Spring上下文中定义Bean的顺序。而最简单的方法是使用@DependsOn批注。

所以我们放置了类似的东西:

@Bean
public SpringLiquibase liquibaseA(
    @Qualifier("dataSourceA") DataSource dataSource,
    @Qualifier("liquibasePropertiesA") LiquibaseProperties liquibaseProperties
) {
    return instantiateSpringLiquibase(dataSource, liquibaseProperties); 
}

@Bean
@DependsOn("liquibaseA")
public SpringLiquibase liquibaseB(
    @Qualifier("dataSourceB") DataSource dataSource,
    @Qualifier("liquibasePropertiesB") LiquibaseProperties liquibaseProperties
) {
    return instantiateSpringLiquibase(dataSource, liquibaseProperties); 
}

private SpringLiquibase instantiateSpringLiquibase(DataSource dataSource, LiquibaseProperties liquibaseProperties) {
    // set the datasource from dataSource and everything else from liquibaseProperties
}

答案 1 :(得分:1)

这不是用于春季启动,但如果您通过更改日志管理迁移,则此解决方法将有所帮助。假设您具有用于不同模式的不同数据源。

<bean id="liquibase1" class="liquibase.integration.spring.SpringLiquibase">
      <property name="dataSource" ref="dataSource1" />
      <property name="changeLog" value="classpath:db1-changelog1.xml" />
 </bean>
 <bean id="liquibase2" depends-on="liquibase1" class="liquibase.integration.spring.SpringLiquibase">
      <property name="dataSource" ref="dataSource2" />
      <property name="changeLog" value="classpath:db2-changelog1.xml" />
 </bean>
<bean id="liquibase3" depends-on="liquibase2"  class="liquibase.integration.spring.SpringLiquibase">
      <property name="dataSource" ref="dataSource1" />
      <property name="changeLog" value="classpath:db1-changelog2.xml" />
 </bean>
<bean id="liquibase4" depends-on="liquibase3"  class="liquibase.integration.spring.SpringLiquibase">
      <property name="dataSource" ref="dataSource2" />
      <property name="changeLog" value="classpath:db2-changelog2.xml" />
 </bean>