在休眠验证之前执行飞行路线迁移

时间:2018-06-26 13:30:24

标签: hibernate spring-boot flyway

我有一个包含多个模块的spring boot项目。我希望他们所有人都有单独的飞行路线配置。 例如:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

<header class="header">
  <div class="header-content">
    <center>
      <div class="header-wrapper animateObject">
        <h1>title</h1>
        <div style="height: 2px; width: 70px; background-color: #fff; margin: 20px;"></div>
        <p>subtitle</p>
      </div>
    </center>
  </div>
</header>

<div style="height: 1000px"></div>

问题与所描述的here相同。简而言之,休眠验证会在flyway之前开始,并且会抛出异常,因为flyway尚未创建表。

那种情况下的解决方案对我不起作用,因为我没有为与休眠连接的bean进行配置(我使用了spring boot AutoConfiguration)。

我检查了FlywayAutoConfiguration并注意到有这样的东西:

@Component
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class })
@PropertySource("classpath:flyway.properties")
public class FlywayConfig {

  @PostConstruct
  public void startMigrations() {
    if(enabled) {
      Flyway flyway = new Flyway();
      flyway.setDataSource(dataSource);
      flyway.setSchemas(schema);
      flyway.setLocations(flywayLocation);
      flyway.setSqlMigrationPrefix(prefix);
      flyway.migrate();
    }
  }
}

但这在我的情况下不起作用。

我不希望在Spring Boot AutoConfiguration中覆盖Bean以便添加@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) (就像我上面发布的问题的解决方案中一样)。我看不出要为flyway配置创建bean的理由,因为它们需要在应用程序启动时执行一次。

我还使用一个父模块,该模块将大多数模块合并在一起,但是有时我想在构建之前排除/包含一个模块。如果我在父模块中必须覆盖的@DependsOn上使用@DependsOn注释,这意味着我将必须在每次构建之前更新代码。

所以,我的问题是:在执行休眠验证之前,还有另一种方法可以强制执行flyway吗?

1 个答案:

答案 0 :(得分:0)

我没有设法找到一种无需创建飞豆就执行飞线迁移的方法,但是我确实设法逃避了@DependsOn注释的使用。

这是我的飞豆的外观:

上载器模块:

 @Configuration
  public class FlywayConfigUploader {

    @Bean("flywayUploader")
    public Flyway startMigrations() {
        Flyway flyway = new Flyway();
        flyway.setDataSource(dataSource);
        flyway.setSchemas(schema);
        flyway.setLocations(flywayLocation);
        flyway.setSqlMigrationPrefix(prefix);
        return flyway;
      }
    }

处理模块:

  @Configuration
  public class FlywayConfigProcessor {

    @Bean("flywayProcessor")
    public Flyway startMigrations() {
      Flyway flyway = new Flyway();
      flyway.setDataSource(dataSource);
      flyway.setSchemas(schema);
      flyway.setLocations(flywayLocation);
      flyway.setSqlMigrationPrefix(prefix);
      return flyway;
    }
  }

该项目目前有10个模块(因此,这些飞行通道配置中有10个)。将来模块的数量可能会增加。

我像this answer一样推翻了LocalContainerEntityManagerFactoryBean。 但是,我没有使用DependsOn批注,而是将所有flyway bean作为对LocalContainerEntityManagerFactoryBean bean的依赖。

  @Bean(name = "entityManagerFactory")
  public LocalContainerEntityManagerFactoryBean
  postgresEntityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource,
      List<Flyway> flywayBeans) {
    flywayBeans.forEach(el -> el.migrate());
    //Rest of the code from the method is not relevant for the question
    }

这样,当用户决定排除或包含模块时,无需更新代码,因为每个模块都有一个仅在构建中包含该模块时才会创建的flyway bean。

这样,我们还可以控制航线迁移的订单执行。例如,我们可能有其他模块所依赖的基本模块,因此必须首先执行从该模块的迁移。在那种情况下,我们可以将飞行路线配置包装在一个包装器Bean中,该包装器将包含有关其顺序的信息。

public class FlywayWrapper {
private Flyway flywayConfig;
private Integer order;
}

在执行迁移之前,我们可以按迁移顺序对其进行排序。

flywayBeans.sort(Comparator.comparing(FlywayWrapper::getOrder));
flywayBeans.forEach(el -> el.getFlywayConfig().migrate());