Использование JdbcTemplate в файлах миграции Java Flyway вызывает цикл зависимости - PullRequest
1 голос
/ 22 октября 2019

Начиная с версии 6. *, Flyway поддерживает внедрение bean-компонентов Spring в файлы миграции 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)
└─────┘

Кажется, я не могу использовать JdbcTemplate в файлах миграции Java, Flyway'sВ документе показано, что я могу создать свой собственный JdbcTemplate, используя Context, например:

public void migrate(Context context) {
        new JdbcTemplate(new SingleConnectionDataSource(context.getConnection(), true))
                .execute("INSERT INTO test_user (name) VALUES ('Obelix')");
}

Но, к сожалению, я не могу контролировать SomeDAO, это из другого модуля, к которому я не могу прикоснуться.

Связанные версии:

  • Пролетный путь: 6.0.6

  • Пружинный пыльник: 2.2.0

Ответы [ 3 ]

0 голосов
/ 23 октября 2019

Вот так Spring Boot решил интегрировать Flyway. В автоконфигурации по умолчанию вы ничего не можете сделать с базой данных до завершения миграции Flyway. Это разумный, но взвешенный выбор.

Взгляните на исходный код FlywayAutoConfiguration . Есть довольно неприятный трюк, который гарантирует, что никто не сможет использовать JdbcTemplate до того, как Flyway будет готов:

        /**
         * 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, но с удаленными хитрыми методами.

Однако вам придется добавить аналогичный прием зависимостей, чтобы гарантировать, что ваши службы / задания будут запускаться только после вашего пользовательскогоПроход готов.

0 голосов
/ 07 ноября 2019

Меня также порадовала эта функция, и я был очень разочарован, обнаружив, что невозможно автоматически связывать классы, которые в некотором роде зависят от уровня сохраняемости. Но решение, описанное в Flyway Spring Boot Autowired Bean с зависимостью JPA , все еще работает:

Первое расширение FlywayConfiguration:

@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);
    }

Во-вторых, создайте этот класс, чтобы получить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);
    }

Теперь вы можете использовать этот класс в своем классе миграции Java (extends BaseJavaMigration), чтобы получить любой Bean-компонент, который вам нужен.

0 голосов
/ 22 октября 2019

Не смотрел вниз по стеку, но я думаю, что Flyway, как инструмент миграции, не хочет, чтобы вы структурировали данные при его изменении ...

Другие сервисы (не доступ к данным) внедряются и могутбыть использованным.

Вы получаете соединение с базой данных из контекста, чтобы изменить его, используя шаблон jdbc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...