在Flyway中使用JdbcTemplate';s的Java迁移文件导致依赖循环

在Flyway中使用JdbcTemplate';s的Java迁移文件导致依赖循环,java,spring-boot,flyway,Java,Spring Boot,Flyway,自版本6.*以来,Flyway支持Springbean注入java迁移文件,并实现了JavaMigration接口。以下是我的例子: @Component public class V1_201809261821__some_migration extends BaseJavaMigration { @Autowired private SomeDAO someDAO; @Override public void migrate(Context context

自版本6.*以来,Flyway支持Springbean注入java迁移文件,并实现了
JavaMigration
接口。以下是我的例子:

@Component
public class V1_201809261821__some_migration extends BaseJavaMigration {

    @Autowired
    private SomeDAO someDAO;

    @Override
    public void migrate(Context context) throws Exception {
        someDAO.doSomething();
    }
}
启动时,它会抱怨:

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   v1_201809261821__some_migration (field private SomeDAO V1_201809261821__some_migration.someDAO)
┌─────┐
|  someDAO (field private org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate someDAO.namedParameterJdbcTemplate)
↑     ↓
|  flywayInitializer defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]
↑     ↓
|  flyway defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]
↑     ↓
|  v1_201809261821__some_migration (field private SomeDAO V1_201809261821__some_migration.someDAO)
└─────┘
似乎我不能在Java迁移文件中使用
JdbcTemplate
,这表明我可以使用
Context
构建自己的
JdbcTemplate
,比如:

public void migrate(Context context) {
        new JdbcTemplate(new SingleConnectionDataSource(context.getConnection(), true))
                .execute("INSERT INTO test_user (name) VALUES ('Obelix')");
}
但不幸的是,我无法控制某个DAO,它来自另一个我无法触摸的模块

相关版本:

  • 飞行路线:6.0.6

  • 弹簧靴:2.2.0


    • 没有向下查看堆栈,但我想作为迁移工具的Flyway不希望您在更改数据时对其进行结构化

      其他(非数据访问)服务被注入并可以使用


      您可以从上下文获取数据库连接,以使用jdbc模板进行更改。

      这就是Spring Boot决定集成Flyway的原因。 在默认自动配置中,在Flyway迁移完成之前,您不能对数据库执行任何操作。这是一个明智但固执己见的选择

      看看的源代码。在Flyway准备就绪之前,有一个相当糟糕的技巧来确保没有人可以使用JdbcTemplate:

              /**
               * Additional configuration to ensure that {@link JdbcOperations} beans depend on
               * the {@code flywayInitializer} bean.
               */
              @Configuration
              @ConditionalOnClass(JdbcOperations.class)
              @ConditionalOnBean(JdbcOperations.class)
              protected static class FlywayInitializerJdbcOperationsDependencyConfiguration
                      extends JdbcOperationsDependsOnPostProcessor {
      
                  public FlywayInitializerJdbcOperationsDependencyConfiguration() {
                      super("flywayInitializer");
                  }
      
              }
      
      为了实现您的目标,您必须禁用此自动配置(
      spring.autoconfigure.exclude
      )并自己编写Flyway配置。您可以从
      FlywayAutoConfiguration
      的源代码开始,但需要删除一些棘手的方法


      但是,您必须添加一个类似的依赖技巧,以确保只有在自定义Flyway准备就绪后才能启动服务/作业。

      我也对这一功能感到兴奋,并且非常失望地发现,无法自动连接以某种方式依赖于持久层的类。 但中描述的解决方案仍然有效:

      第一次扩展
      飞行路线配置

      @Configuration
      @ComponentScan
      @ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
      class DatabaseMigrationConfiguration extends FlywayConfiguration {
      
          @Override
          public Flyway flyway(FlywayProperties properties, DataSourceProperties dataSourceProperties,
              ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
              ObjectProvider<DataSource> flywayDataSource,
              ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
              ObjectProvider<JavaMigration> javaMigrations,
              ObjectProvider<Callback> callbacks) {
              return super.flyway(properties, dataSourceProperties, resourceLoader, dataSource, flywayDataSource, fluentConfigurationCustomizers,
                  javaMigrations, callbacks);
          }
      
          @Primary
          @Bean(name = "flywayInitializer")
          @DependsOn({ "springUtility" })
          @ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
          public FlywayMigrationInitializer flywayInitializer(Flyway flyway,
              ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
              return super.flywayInitializer(flyway, migrationStrategy);
          }
      
      @配置
      @组件扫描
      @ConditionalOnProperty(prefix=“spring.flyway”,name=“enabled”,matchIfMissing=true)
      类DatabaseMigrationConfiguration扩展了FlywayConfiguration{
      @凌驾
      公共飞行道飞行道(飞行道属性、数据源属性、数据源属性、,
      ResourceLoader ResourceLoader,ObjectProvider数据源,
      ObjectProvider flywayDataSource,
      ObjectProvider fluentConfigurationCustomizers,
      ObjectProviderJavaMigrations,
      对象提供程序回调){
      返回super.flyway(属性、dataSourceProperties、resourceLoader、dataSource、flywayDataSource、FluentConfigurationCustomizer、,
      JavaMigration、回调);
      }
      @初级的
      @Bean(name=“flywayInitializer”)
      @DependsOn({“springUtility”})
      @ConditionalOnProperty(prefix=“spring.flyway”,name=“enabled”,matchIfMissing=true)
      公共飞行道迁移初始化器飞行道初始化器(飞行道,
      ObjectProvider迁移策略){
      返回super.flyway初始值设定项(flyway,migrationStrategy);
      }
      
      其次,创建此类以从应用程序上下文获取Bean:

      @Component
      public class SpringUtility implements ApplicationContextAware {
      
          @Autowired
          private static ApplicationContext applicationContext;
      
          public void setApplicationContext(final ApplicationContext applicationContext) {
              this.applicationContext = applicationContext;
          }
      
          /*
              Get a class bean from the application context
           */
          static <T> T getBean(final Class<T> clazz) {
              return applicationContext.getBean(clazz);
          }
      
      @组件
      公共类SpringUtility实现ApplicationContextAware{
      @自动连线
      私有静态应用上下文应用上下文;
      public void setApplicationContext(最终ApplicationContext ApplicationContext){
      this.applicationContext=applicationContext;
      }
      /*
      从应用程序上下文获取类bean
      */
      静态T getBean(最终类clazz){
      返回applicationContext.getBean(clazz);
      }
      

      现在,您可以在java迁移类中使用这个类(
      扩展BaseJavaMigration
      )获取您想要的任何Bean。

      您在这个问题上运气好吗?或者您找到任何解决方法了吗,我也有完全相同的问题。@FolgerFonseca我通过找到一种方法来修改
      SomeDAO
      ,这打破了问题设置的限制。。。