代码之家  ›  专栏  ›  技术社区  ›  Dimitar Spasovski

在休眠验证之前执行Flyway迁移

  •  0
  • Dimitar Spasovski  · 技术社区  · 6 年前

    我有一个Spring引导项目,它有多个模块。我希望他们都有单独的飞行路线配置。 例如:

    @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();
        }
      }
    }
    

    问题与描述的问题相同 here .简言之,休眠验证在Flyway之前开始,并引发异常,因为Flyway尚未创建表。

    这种情况下的解决方案对我不起作用,因为我没有与Hibernate连接的bean的配置(我使用Spring引导自动配置)。

    我查看了FlywayAutoconfiguration,发现有如下情况:

    @AutoConfigureAfter({ DataSourceAutoConfiguration.class,
            HibernateJpaAutoConfiguration.class })
    

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

    为了添加 @DependsOn (就像我在上面发布的问题的解决方案一样)。我没有看到为flyway配置创建bean的原因,因为它们需要在应用程序启动时执行一次。

    我还使用了一个父模块,它将大多数模块合并在一起,但有时我想在构建之前排除/包括一个模块。如果我使用 @依赖 上的批注 bean 我必须在父模块中重写,这意味着我必须在每次生成之前更新代码。

    所以,我的问题是:在执行Hibernate验证之前,是否还有其他方法强制执行Flyway?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Dimitar Spasovski    6 年前

    我没有找到一种不创建flyway bean就执行flyway迁移的方法,但我确实设法避免了使用 @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个这样的立交桥配置)。将来模块的数量可能会增加。

    我骑过了 LocalContainerEntityManagerFactoryBean 就像在 this answer . 但不是使用 DependsOn 注释我添加了所有的Flyway bean作为对 本地ContainerEntityManagerFactoryBean 豆子。

      @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。

    通过这种方式,我们还可以控制Flyway迁移的订单执行。例如,我们可能有一个其他模块依赖的基本模块,因此必须首先执行来自该模块的迁移。在这种情况下,我们可以将Flyway配置包装在包装bean中,包装bean将包含有关其顺序的信息。

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

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

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