2016-01-21 14 views
10

フライウェイマイグレーションのJavaコードに構成プロパティのコンポーネントを注入しようとしていますが、常にnullです。フライウェイのJavaベースのマイグレーションでスプリングビーンが注入されない

私はフライウェイでスプリングブートを使用しています。

@Component 
@ConfigurationProperties(prefix = "code") 
public class CodesProp { 

    private String codePath; 
} 

はその後フライウェイの移行コード内で、次のように、このコンポーネントをautowrireしようとしている:

public class V1_4__Migrate_codes_metadata implements SpringJdbcMigration { 

@Autowired 
private CodesProp codesProp ; 
public void migrate(JdbcTemplate jdbcTemplate) throws Exception { 
    codesProp.getCodePath(); 
} 

をここで、codesPropは常にnullです。

フライウェイの中に春の豆を入れたり、フライウェイビーンの前に初期化する方法はありますか?

ありがとうございます。

答えて

5

フライウェイはSpringJdbcMigrationの実装への依存性注入をサポートしていません。 SpringJdbcMigrationを実装するクラスパス上のクラスを探し、既定のコンストラクターを使用して新しいインスタンスを作成します。これはSpringJdbcMigrationResolverで実行されます。移行が実行されると、SpringJdbcMigrationExecutorは新しいJdbcTemplateを作成し、移行実装のmigrateメソッドを呼び出します。

Javaベースの移行に依存関係を注入する必要がある場合は、アプリケーションコンテキストから特定のタイプのBeanを取得し、それぞれに対してResolvedMigrationインスタンスを返す独自のMigrationResolverを実装する必要があると思います。

+0

おかげで、私は、今、私はファイルシステムに格納されているいくつかのコードをインポートする必要があり、それが問題https://github.com/flyway/flyway/issues/1062によって関連していると思いますDBに。あなたは構成として外部経路を読んで、それを飛行経路に渡す考えがありますか? – Mango

3

私のように、あなたはフライウェイ4.1を待つしたくない場合は、フライウェイ4.0を使用して、春のブートアプリケーションに以下を追加することができます。

1)プロジェクトでApplicationContextAwareSpringJdbcMigrationResolverクラスを作成します。

を私はいくつかの依存ハードコードされている

import org.flywaydb.core.Flyway; 
import org.flywaydb.core.internal.dbsupport.DbSupport; 
import org.flywaydb.core.internal.dbsupport.h2.H2DbSupport; 
import org.flywaydb.core.internal.dbsupport.mysql.MySQLDbSupport; 
import com.pegusapps.zebra.infrastructure.repository.flyway.ApplicationContextAwareSpringJdbcMigrationResolver; 
import org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver; 
import org.flywaydb.core.internal.util.Location; 
import org.flywaydb.core.internal.util.PlaceholderReplacer; 
import org.flywaydb.core.internal.util.scanner.Scanner; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 

import javax.sql.DataSource; 
import java.sql.SQLException; 

@Configuration 
@ComponentScan("db.migration") 
public class FlywayConfiguration { 

    @Bean 
    public BeanPostProcessor postProcessFlyway(ApplicationContext context) { 
     return new BeanPostProcessor() { 

      @Override 
      public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { 
       return o; 
      } 

      @Override 
      public Object postProcessAfterInitialization(Object o, String s) throws BeansException { 
       if (o instanceof Flyway) { 
        Flyway flyway = (Flyway) o; 
        flyway.setSkipDefaultResolvers(true); 
        ApplicationContextAwareSpringJdbcMigrationResolver resolver = new ApplicationContextAwareSpringJdbcMigrationResolver(
          new Scanner(Thread.currentThread().getContextClassLoader()), 
          new Location("classpath:db/migration"), 
          context.getBean(org.flywaydb.core.api.configuration.FlywayConfiguration.class), 
          context); 
        SqlMigrationResolver sqlMigrationResolver = null; 
        try { 
         sqlMigrationResolver = new SqlMigrationResolver(
           getDbSupport(), 
           new Scanner(Thread.currentThread().getContextClassLoader()), 
           new Location("classpath:db/migration"), 
           PlaceholderReplacer.NO_PLACEHOLDERS, 
           "UTF-8", 
           "V", 
           "R", 
           "__", 
           ".sql"); 
        } catch (SQLException e) { 
         e.printStackTrace(); 
        } 
        flyway.setResolvers(sqlMigrationResolver, resolver); 
       } 
       return o; 
      } 

      private DbSupport getDbSupport() throws SQLException { 
       DataSource dataSource = context.getBean(DataSource.class); 
       if(((org.apache.tomcat.jdbc.pool.DataSource)dataSource).getDriverClassName().equals("org.h2.Driver")) 
       { 
        return new H2DbSupport(dataSource.getConnection()); 
       } 
       else 
       { 
        return new MySQLDbSupport(dataSource.getConnection()); 
       } 
      } 
     }; 
    } 
} 

注:

import org.flywaydb.core.api.FlywayException; 
import org.flywaydb.core.api.MigrationType; 
import org.flywaydb.core.api.MigrationVersion; 
import org.flywaydb.core.api.configuration.FlywayConfiguration; 
import org.flywaydb.core.api.migration.MigrationChecksumProvider; 
import org.flywaydb.core.api.migration.MigrationInfoProvider; 
import org.flywaydb.core.api.migration.spring.SpringJdbcMigration; 
import org.flywaydb.core.api.resolver.ResolvedMigration; 
import org.flywaydb.core.internal.resolver.MigrationInfoHelper; 
import org.flywaydb.core.internal.resolver.ResolvedMigrationComparator; 
import org.flywaydb.core.internal.resolver.ResolvedMigrationImpl; 
import org.flywaydb.core.internal.resolver.spring.SpringJdbcMigrationExecutor; 
import org.flywaydb.core.internal.resolver.spring.SpringJdbcMigrationResolver; 
import org.flywaydb.core.internal.util.ClassUtils; 
import org.flywaydb.core.internal.util.Location; 
import org.flywaydb.core.internal.util.Pair; 
import org.flywaydb.core.internal.util.StringUtils; 
import org.flywaydb.core.internal.util.scanner.Scanner; 
import org.springframework.context.ApplicationContext; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.Map; 

/** 
* Migration resolver for {@link SpringJdbcMigration}s which are registered in the given {@link ApplicationContext}. 
* This resolver provides the ability to use other beans registered in the {@link ApplicationContext} and reference 
* them via Spring's dependency injection facility inside the {@link SpringJdbcMigration}s. 
*/ 
public class ApplicationContextAwareSpringJdbcMigrationResolver extends SpringJdbcMigrationResolver { 

    private final ApplicationContext applicationContext; 

    public ApplicationContextAwareSpringJdbcMigrationResolver(Scanner scanner, Location location, FlywayConfiguration configuration, ApplicationContext applicationContext) { 
     super(scanner, location, configuration); 
     this.applicationContext = applicationContext; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public Collection<ResolvedMigration> resolveMigrations() { 
     // get all beans of type SpringJdbcMigration from the application context 
     Map<String, SpringJdbcMigration> springJdbcMigrationBeans = 
       (Map<String, SpringJdbcMigration>) this.applicationContext.getBeansOfType(SpringJdbcMigration.class); 

     ArrayList<ResolvedMigration> resolvedMigrations = new ArrayList<ResolvedMigration>(); 

     // resolve the migration and populate it with the migration info 
     for (SpringJdbcMigration springJdbcMigrationBean : springJdbcMigrationBeans.values()) { 
      ResolvedMigrationImpl resolvedMigration = extractMigrationInfo(springJdbcMigrationBean); 
      resolvedMigration.setPhysicalLocation(ClassUtils.getLocationOnDisk(springJdbcMigrationBean.getClass())); 
      resolvedMigration.setExecutor(new SpringJdbcMigrationExecutor(springJdbcMigrationBean)); 

      resolvedMigrations.add(resolvedMigration); 
     } 

     Collections.sort(resolvedMigrations, new ResolvedMigrationComparator()); 
     return resolvedMigrations; 
    } 

    ResolvedMigrationImpl extractMigrationInfo(SpringJdbcMigration springJdbcMigration) { 
     Integer checksum = null; 
     if (springJdbcMigration instanceof MigrationChecksumProvider) { 
      MigrationChecksumProvider version = (MigrationChecksumProvider) springJdbcMigration; 
      checksum = version.getChecksum(); 
     } 

     String description; 
     MigrationVersion version1; 
     if (springJdbcMigration instanceof MigrationInfoProvider) { 
      MigrationInfoProvider resolvedMigration = (MigrationInfoProvider) springJdbcMigration; 
      version1 = resolvedMigration.getVersion(); 
      description = resolvedMigration.getDescription(); 
      if (!StringUtils.hasText(description)) { 
       throw new FlywayException("Missing description for migration " + version1); 
      } 
     } else { 
      String resolvedMigration1 = ClassUtils.getShortName(springJdbcMigration.getClass()); 
      if (!resolvedMigration1.startsWith("V") && !resolvedMigration1.startsWith("R")) { 
       throw new FlywayException("Invalid Jdbc migration class name: " + springJdbcMigration.getClass() 
                            .getName() + " => ensure it starts with V or R," + " or implement org.flywaydb.core.api.migration.MigrationInfoProvider for non-default naming"); 
      } 

      String prefix = resolvedMigration1.substring(0, 1); 
      Pair info = MigrationInfoHelper.extractVersionAndDescription(resolvedMigration1, prefix, "__", ""); 
      version1 = (MigrationVersion) info.getLeft(); 
      description = (String) info.getRight(); 
     } 

     ResolvedMigrationImpl resolvedMigration2 = new ResolvedMigrationImpl(); 
     resolvedMigration2.setVersion(version1); 
     resolvedMigration2.setDescription(description); 
     resolvedMigration2.setScript(springJdbcMigration.getClass().getName()); 
     resolvedMigration2.setChecksum(checksum); 
     resolvedMigration2.setType(MigrationType.SPRING_JDBC); 
     return resolvedMigration2; 
    } 
} 

2)春ブーツフライウェイのインスタンスを生成したプロセスを投稿する新しい構成クラスを追加します。 tomcat jdbc pool、h2、およびmysqlを使用します。何か他のものを使用している場合は、コードを変更する必要があります(避ける方法が分かっている人はコメントしてください)。

また、@ComponentScanパッケージは、 Java移行クラス。

また、移行のSQLとJavaの両方の風味をサポートしたいので、SqlMigrationResolverを追加しなければならなかったことにも注意してください。あなたはクラス@Componentを作成する必要があり

@Component 
public class V2__add_default_surveys implements SpringJdbcMigration { 

    private final SurveyRepository surveyRepository; 

    @Autowired 
    public V2__add_surveys(SurveyRepository surveyRepository) { 
     this.surveyRepository = surveyRepository; 
    } 

    @Override 
    public void migrate(JdbcTemplate jdbcTemplate) throws Exception { 
     surveyRepository.save(...); 
    } 
} 

注意をし、それがSpringJdbcMigrationを実装する必要があります。

3)は、実際の移行を行いdb.migrationsパッケージ内のJavaクラスを作成します。このクラスでは、マイグレーションを行う必要があるかもしれないコンテキストからの任意のSpring BeanにSpringコンストラクタインジェクションを使用できます。

注:

spring.jpa.hibernate.ddl-auto=none 
13

この機能はFlyway 5.0に追加されているように見えます:検証はフライウェイの実行前に実行するようなので、休止状態のDDLの検証を無効にしてください。この質問は、Googleで「春の豆」を検索したときの最初の結果として出てきました。そのため、他の人が引き続きこの問題に取り組んでいる可能性があります。

あなたがFlyway 4.0で立ち往生している場合、私はspring-beans-flyway repository on my GitHubページに掲載されている別のクイックソリューションを思いつきました。

1)Tell Spring to do a component scan of your db.migration directory

@SpringBootApplicationに加えて@ComponentScan注釈を追加できます。

@SpringBootApplication 
@ComponentScan({ "com.avehlies.springbeansflyway", "db.migration" }) 
public class SpringBeansFlywayApplication 

2)あなたが実際にJdbcTemplateを使用していないでしょうがCreate a SpringJdbcMigration in your db.migrations directory.

あなたは、実装migrate(JdbcTemplate)方法の内のコードを入れます。これにより、あなたのヘルパークラスにSpring関連の作業をさせながら、Flywayが順番に移行を実行します。

public class V2__Add_Person implements SpringJdbcMigration { 
    public void migrate(JdbcTemplate jdbcTemplate) { 
     Person person = new Person(4, 'Cosmo Kramer'); 
     AddPerson.addPerson(person); 
    } 
} 

3)Make a class annotated as a Component and create static methods in it.

あなたは、コンストラクタの内部で必要な豆を注入することができます。 V ###の移行では、これらの静的メソッドを使用して、Spring-wired Beanを操作できます。

@Component 
public class AddPerson { 
    private static PersonRepository personRepository; 

    public AddPerson(PersonRepository personRepository) { 
     this.personRepository = personRepository; 
    } 

    public static int addPerson(Person person) { 
     return personRepository.save(person); 
    } 
} 
0

deltaspikeを使用している場合は、BeanProviderを使用してクラスへの参照を取得できます。ここでDAOの例ですが、あなたのクラスでもうまくいくはずです。あなたの参照を持っている

UserDao userdao = UserDao.getInstance(); 

そして、そこ:あなたの移行方法に続いて

public static UserDao getInstance() { 
    return BeanProvider.getContextualReference(UserDao.class, false, new DaoLiteral()); 
} 

は、あなたのDAOコードを変更し

。 (から参照:Flyway Migration with java

関連する問題