由于我对 JPA 的依赖,我为此苦苦挣扎了很长时间。我将稍微编辑我的问题的标题以反映这一点......
@Autowired bean 是从 ApplicationContext 实例化的。我们可以创建一个不同的 bean ApplicationContextAware 并使用它来“手动连接”我们的 bean 以用于迁移。
可以找到一个非常干净的方法here。不幸的是,这在使用 JPA 时会引发未捕获的异常(具体而言,ApplicationContext 为空)。幸运的是,我们可以通过使用@DependsOn 注解并在设置ApplicationContext 后强制flyway 运行来解决这个问题。
首先我们需要来自上述avehlies/spring-beans-flyway2 的SpringUtility。
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;
}
}
然后,为springUtility 配置flywayInitializer 和@DependsOn。我在这里扩展了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,因为后者已弃用。另外,看看下面的twocomments用户Wim Deblauwe。