由于依赖JPA,我为此苦了很长时间。我将略微修改我的问题的标题以反映这一点。
@Autowired
Bean是从实例化的ApplicationContext
。我们可以创建一个不同的bean,ApplicationContextAware
然后使用它“手动连接”我们的bean以供迁移。
在这里可以找到一种非常干净的方法。不幸的是,ApplicationContext
使用JPA时会引发未捕获的异常(特别是null)。幸运的是,我们可以通过使用@DependsOn
注释并ApplicationContext
在设置之后强制飞行来解决此问题。
首先我们需要SpringUtility
从avehlies/spring-beans- flyway2
以上。
package com.mypackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@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
*/
public static <T> T getBean(final Class clazz) {
return (T) applicationContext.getBean(clazz);
}
/*
Return the application context if necessary for anything else
*/
public static ApplicationContext getContext() {
return applicationContext;
}
}
随后,将配置flywayInitializer
有@DependsOn
供springUtility
。我扩展了FlywayAutoConfiguration
此处,希望保留自动配置功能。除了在gradle.build文件中关闭flyway不再起作用之外,这似乎对我来说一直有效,因此我不得不添加,@Profile("!integration")
以防止它在测试期间运行。除此之外,自动配置似乎对我有用,但是坦白地说,我只运行了一次迁移。希望如果我错了,有人会纠正我。
package com.mypackage;
import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.DependsOn;
import com.mypackage.SpringUtility;
@Configuration
@Profile("!integration")
class MyFlywayConfiguration extends FlywayConfiguration {
@Primary
@Bean(name = "flywayInitializer")
@DependsOn("springUtility")
public FlywayMigrationInitializer flywayInitializer(Flyway flyway){
return super.flywayInitializer(flyway);
//return new FlywayMigrationInitializer(flyway, null);
}
}
为了完成示例,下面是一个迁移:
package db.migration;
import org.flywaydb.core.api.migration.spring.BaseSpringJdbcMigration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import com.mypackage.repository.AccountRepository;
import com.mypackage.domain.Account;
import com.mypackage.SpringUtility;
import java.util.List;
public class V2__account_name_ucase_firstname extends BaseSpringJdbcMigration {
private AccountRepository accountRepository = SpringUtility.getBean(AccountRepository.class);
public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
List<Account> accounts = accountRepository.findAll();
for (Account account : accounts) {
String firstName = account.getFirstName();
account.setFirstName(firstName.substring(0, 1).toUpperCase() + firstName.substring(1));
account = accountRepository.save(account);
}
}
}
感谢github上的avehlies,堆栈溢出的Andy Wilkinson和github上的OldIMP一直为我提供帮助。
如果您使用的是Flyway的最新版本,请扩展BaseJavaMigration
而不是BaseSpringJdbcMigration
不推荐使用。另外,请查看用户Wim Deblauwe 的以下两条评论。