Выполнить миграцию с пролета перед проверкой гибернации - PullRequest
0 голосов
/ 26 июня 2018

У меня есть проект с весенней загрузкой, который имеет несколько модулей. Я хотел бы, чтобы у всех них были отдельные конфигурации пролета. Например:

@Component
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class })
@PropertySource("classpath:flyway.properties")
public class FlywayConfig {

  @PostConstruct
  public void startMigrations() {
    if(enabled) {
      Flyway flyway = new Flyway();
      flyway.setDataSource(dataSource);
      flyway.setSchemas(schema);
      flyway.setLocations(flywayLocation);
      flyway.setSqlMigrationPrefix(prefix);
      flyway.migrate();
    }
  }
}

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

Решение в этом случае не работает для меня, потому что у меня нет конфигурации для bean-компонентов, связанных с hibernate (я использую весеннюю загрузку AutoConfiguration).

Я проверил конфигурацию FlywayAutoConfiguration и заметил, что есть что-то вроде этого:

@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })

Но в моем случае это не работает.

Я бы предпочел не переопределять bean-компоненты из автоконфигурации при загрузке, чтобы добавить @DependsOn (как в решении вопроса, который я выложил выше). Я не вижу причины для создания bean-компонента для конфигураций flyway, потому что они должны быть выполнены один раз, при запуске приложения.

Я также использую родительский модуль, который объединяет большинство модулей вместе, но иногда я хотел бы исключить / включить модуль перед сборкой. Если я использую аннотацию @DependsOn для bean, которую мне придется переопределить в родительском модуле, это будет означать, что мне придется обновлять код перед каждой сборкой.

Итак, мой вопрос: есть ли другой способ принудительно запустить выполнение пролетного пути перед выполнением проверки гибернации?

1 Ответ

0 голосов
/ 01 июля 2018

Мне не удалось найти способ выполнить миграцию на пути без создания bean-компонентов, но мне удалось избежать использования аннотации @DependsOn.

Вот как выглядят мои бобы:

Модуль загрузки:

 @Configuration
  public class FlywayConfigUploader {

    @Bean("flywayUploader")
    public Flyway startMigrations() {
        Flyway flyway = new Flyway();
        flyway.setDataSource(dataSource);
        flyway.setSchemas(schema);
        flyway.setLocations(flywayLocation);
        flyway.setSqlMigrationPrefix(prefix);
        return flyway;
      }
    }

Модуль обработки:

  @Configuration
  public class FlywayConfigProcessor {

    @Bean("flywayProcessor")
    public Flyway startMigrations() {
      Flyway flyway = new Flyway();
      flyway.setDataSource(dataSource);
      flyway.setSchemas(schema);
      flyway.setLocations(flywayLocation);
      flyway.setSqlMigrationPrefix(prefix);
      return flyway;
    }
  }

В настоящее время в проекте имеется 10 модулей (таким образом, имеется 10 таких конфигураций пролета). Количество модулей, вероятно, увеличится в будущем.

Я отверг LocalContainerEntityManagerFactoryBean, как в этот ответ . Но вместо использования аннотации DependsOn я добавил все bean-компоненты flyway в качестве зависимости к bean-компоненту LocalContainerEntityManagerFactoryBean.

  @Bean(name = "entityManagerFactory")
  public LocalContainerEntityManagerFactoryBean
  postgresEntityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource,
      List<Flyway> flywayBeans) {
    flywayBeans.forEach(el -> el.migrate());
    //Rest of the code from the method is not relevant for the question
    }

Таким образом, нет необходимости в обновлении кода, когда пользователь решает исключить или включить модули, потому что каждый модуль имеет bean-компонент flyway, который будет создан, только если модуль включен в сборку.

Таким образом, мы также можем контролировать выполнение заказа на миграцию. Например, у нас может быть базовый модуль, от которого зависят другие модули, поэтому миграции из этого модуля должны выполняться в первую очередь. В этом сценарии мы могли бы обернуть конфигурации flyway в оболочку bean, которая будет содержать информацию об их заказе.

public class FlywayWrapper {
private Flyway flywayConfig;
private Integer order;
}

Перед выполнением миграций мы могли бы отсортировать их по их порядку.

flywayBeans.sort(Comparator.comparing(FlywayWrapper::getOrder));
flywayBeans.forEach(el -> el.getFlywayConfig().migrate());
...