Spring Boot Flyway Sping Boot Autowired Bean(依赖JPA)

klsxnrf1  于 2024-01-06  发布在  Spring
关注(0)|答案(5)|浏览(208)

我使用的是Flyway 5.0.5,我无法创建一个带有自动连接属性的java(SpringJdbcMigration).它们最终变成了null
我能找到的最接近的是这个问题:Spring beans are not injected in flyway java based migration
答案提到它在Flyway 5中被修复,但链接已经死了。
我错过了什么?

pb3s4cty

pb3s4cty1#

由于我对JPA的依赖,我为此挣扎了很长时间。我将稍微编辑一下我的问题的标题,以反映这一点。
@Autowired bean是从ApplicationContext示例化的。我们可以创建一个不同的bean,即ApplicationContextAware,并使用它来“手动连接”我们的bean以用于迁移。
here是一个非常简洁的方法。不幸的是,在使用JPA时,这会抛出一个未捕获的异常(具体来说,ApplicationContext为null)。幸运的是,我们可以通过使用@DependsOn注解来解决这个问题,并在设置ApplicationContext后强制运行flyway。
首先,我们需要上面的avehlies/spring-beans-flyway2中的SpringUtility

  1. package com.mypackage;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.ApplicationContextAware;
  5. import org.springframework.stereotype.Component;
  6. @Component
  7. public class SpringUtility implements ApplicationContextAware {
  8. private static ApplicationContext applicationContext;
  9. public void setApplicationContext(final ApplicationContext applicationContext) {
  10. this.applicationContext = applicationContext;
  11. }
  12. /*
  13. Get a class bean from the application context
  14. */
  15. public static <T> T getBean(final Class clazz) {
  16. return (T) applicationContext.getBean(clazz);
  17. }
  18. /*
  19. Return the application context if necessary for anything else
  20. */
  21. public static ApplicationContext getContext() {
  22. return applicationContext;
  23. }
  24. }

字符串
然后,为springUtility配置一个flywayInitializer和一个@DependsOn。我在这里扩展了FlywayAutoConfiguration,希望保留自动配置功能。这似乎对我很有效,除了在我的www.example.com文件中关闭flywaygradle.build不再起作用,所以我不得不添加@Profile("!integration"),以防止它在我的测试期间运行。除此之外,自动配置似乎对我有用,但无可否认,我只运行了一次迁移。希望有人如果我错了,他会纠正我的。

  1. package com.mypackage;
  2. import org.flywaydb.core.Flyway;
  3. import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
  4. import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayConfiguration;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.context.annotation.Profile;
  8. import org.springframework.context.annotation.Primary;
  9. import org.springframework.context.annotation.DependsOn;
  10. import com.mypackage.SpringUtility;
  11. @Configuration
  12. @Profile("!integration")
  13. class MyFlywayConfiguration extends FlywayConfiguration {
  14. @Primary
  15. @Bean(name = "flywayInitializer")
  16. @DependsOn("springUtility")
  17. public FlywayMigrationInitializer flywayInitializer(Flyway flyway){
  18. return super.flywayInitializer(flyway);
  19. //return new FlywayMigrationInitializer(flyway, null);
  20. }
  21. }


为了完成这个例子,这里是一个迁移:

  1. package db.migration;
  2. import org.flywaydb.core.api.migration.spring.BaseSpringJdbcMigration;
  3. import org.springframework.jdbc.core.JdbcTemplate;
  4. import org.springframework.stereotype.Component;
  5. import com.mypackage.repository.AccountRepository;
  6. import com.mypackage.domain.Account;
  7. import com.mypackage.SpringUtility;
  8. import java.util.List;
  9. public class V2__account_name_ucase_firstname extends BaseSpringJdbcMigration {
  10. private AccountRepository accountRepository = SpringUtility.getBean(AccountRepository.class);
  11. public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
  12. List<Account> accounts = accountRepository.findAll();
  13. for (Account account : accounts) {
  14. String firstName = account.getFirstName();
  15. account.setFirstName(firstName.substring(0, 1).toUpperCase() + firstName.substring(1));
  16. account = accountRepository.save(account);
  17. }
  18. }
  19. }


感谢github上的avehlies,堆栈溢出的Andy威尔金森和github上的OldIMP,他们沿着帮助了我。
如果你使用的是Flyway的更新版本,那么扩展BaseJavaMigration而不是BaseSpringJdbcMigration,因为后者已经过时了。另外,看看下面用户Wim Deblauwe的两条评论。

展开查看全部
z4iuyo4d

z4iuyo4d2#

该功能还没有进入Flyway。它正在被this issue跟踪。在撰写本文时,该问题尚未解决,并被分配到5.1.0里程碑。

kb5ga3dv

kb5ga3dv3#

看来@mararn1618提供的更新答案在官方文档中记录,所以我将在这里提供一个工作设置。感谢@mararn1618在这个方向上的指导。
免责声明,它是用Kotlin写的:)
首先,您需要一个用于加载迁移类的配置,在Sping Boot (可能还有Spring)中,您需要FlywayConfigurationCustomizer的实现或FlywayAutoConfiguration.FlywayConfiguration的设置。

配置a,已测试

  1. import org.flywaydb.core.api.configuration.FluentConfiguration
  2. import org.flywaydb.core.api.migration.JavaMigration
  3. import org.springframework.beans.factory.annotation.Autowired
  4. import org.springframework.boot.autoconfigure.flyway.FlywayConfigurationCustomizer
  5. import org.springframework.context.ApplicationContext
  6. import org.springframework.stereotype.Component
  7. @Component
  8. class MyFlywayConfiguration @Autowired constructor(
  9. val applicationContext: ApplicationContext
  10. ) : FlywayConfigurationCustomizer {
  11. override fun customize(configuration: FluentConfiguration?) {
  12. val migrationBeans = applicationContext.getBeansOfType(JavaMigration::class.java)
  13. val migrationBeansAsArray = migrationBeans.values.toTypedArray()
  14. configuration?.javaMigrations(*migrationBeansAsArray)
  15. }
  16. }

字符串

配置选项B,未经测试,但也应该工作

  1. import org.flywaydb.core.api.migration.JavaMigration
  2. import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
  3. import org.springframework.boot.autoconfigure.flyway.FlywayConfigurationCustomizer
  4. import org.springframework.context.ApplicationContext
  5. import org.springframework.context.annotation.Bean
  6. import org.springframework.context.annotation.Configuration
  7. @Configuration
  8. class MyFlywayConfiguration : FlywayAutoConfiguration.FlywayConfiguration() {
  9. @Bean
  10. fun flywayConfigurationCustomizer(applicationContext: ApplicationContext): FlywayConfigurationCustomizer {
  11. return FlywayConfigurationCustomizer { flyway ->
  12. val p = applicationContext.getBeansOfType(JavaMigration::class.java)
  13. val v = p.values.toTypedArray()
  14. flyway.javaMigrations(*v)
  15. }
  16. }
  17. }


有了它,你可以像其他Spring bean一样编写迁移:

  1. import org.flywaydb.core.api.migration.BaseJavaMigration
  2. import org.flywaydb.core.api.migration.Context
  3. import org.springframework.beans.factory.annotation.Autowired
  4. import org.springframework.stereotype.Component
  5. @Component
  6. class V7_1__MyMigration @Autowired constructor(
  7. ) : BaseJavaMigration() {
  8. override fun migrate(context: Context?) {
  9. TODO("go crazy, mate, now you can import beans, but be aware of circular dependencies")
  10. }
  11. }


旁注:

  • 小心循环依赖,您的迁移很可能不依赖于存储库(这也是有意义的,毕竟您正在准备它们)
  • 确保您的迁移位于Spring扫描类的位置。
  • 我还没有测试过,但很可能应该谨慎混合这些迁移的路径和Flyway扫描迁移的位置
展开查看全部
0g0grzrc

0g0grzrc4#

如果你正在使用deltaspike,你可以使用BeanProvider来获取对你的DAO的引用。
更改您的DAO代码:

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

字符串
然后在您的迁移方法中:

  1. UserDao userdao = UserDao.getInstance();


这就是你的推荐人
(来源:Flyway Migration with Java)

xqk2d5yq

xqk2d5yq5#

当前的flyway 6.5.5版本已经发布,并且从6.0.0版本返回,我相信已经提供了对spring beans的支持。(使用@autowired),但直觉是您的Migration类也应该由Spring管理以解决依赖关系。有一个很酷且简单的方法,通过覆盖Flyway的默认行为,查看https://reflectoring.io/database-migration-spring-boot-flyway/这篇文章用代码片段清楚地回答了你的问题。

相关问题