Spring Boot 2.1.0 с Flyway 4.2.0

Я хотел бы обновить мои новые проекты до Spring Boot версии 2.1.0, но я ограничен базой данных Oracle 11, которая поддерживается библиотекой Flyway 4.2.0. Все работает нормально в Spring Boot версии 2.0.5 Release, но при переходе к версии 2.1.0 я получаю эту ошибку:

java.lang.NoClassDefFoundError: 
org/flywaydb/core/api/configuration/FluentConfiguration

Конфигурация POM выглядит следующим образом:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <ojdbc6.version>11.2.0.1</ojdbc6.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>${ojdbc6.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
        <version>4.2.0</version>
    </dependency>
</dependencies>

ОБНОВИТЬ

Я могу решить проблему с помощью @Configuration (или, конечно, добавить к основному классу), но дело в том, что это ошибка или функция? До версии 2.1.0 все было выполнено с помощью автоконфигурации, и оно работает готово.

@Bean(initMethod = "migrate")
Flyway flyway() {
    Flyway flyway = new Flyway();
    flyway.setBaselineOnMigrate(true);
    flyway.setDataSource("jdbc:oracle:thin:@localhost:1521:xe", "USER", "PASSWORD1");
    return flyway;
}

Ответ 1

У меня была такая же проблема с PostgreSQL 9.2, и для решения этой проблемы использовался следующий класс.

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

@Configuration
class FlywayConfig {
    @Bean
    fun flyway(dataSource: DataSource): Flyway {
        val flyway = Flyway()
        flyway.dataSource = dataSource
        return flyway
    }

    @Bean
    fun flywayInitializer(flyway: Flyway): FlywayMigrationInitializer {
        return FlywayMigrationInitializer(flyway, null)
    }

    /**
     * Additional configuration to ensure that [EntityManagerFactory] beans depend on the
     * 'flywayInitializer' bean.
     */
    @Configuration
    class FlywayInitializerJpaDependencyConfiguration : EntityManagerFactoryDependsOnPostProcessor("flywayInitializer")
}

PS: это код Котлина, но вы должны легко перевести его на Java.

Ответ 2

Я сделал конфигурацию Spring Spring 2.1.1 и должен был переопределить компонент FlywayDefaultDdlModeProvider.

@Configuration
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
public class LegacyFlywayAutoConfiguration {

    @Bean
    @Primary
    public SchemaManagementProvider flywayDefaultDdlModeProvider(ObjectProvider<Flyway> flyways) {
        return new SchemaManagementProvider() {
            @Override
            public SchemaManagement getSchemaManagement(DataSource dataSource) {
                return SchemaManagement.MANAGED;
            }
        };
    }

    @Bean(initMethod = "migrate")
    public Flyway flyway(DataSource dataSource) {
        Flyway flyway = new Flyway();
        flyway.setBaselineOnMigrate(true);
        flyway.setDataSource(dataSource);
        return flyway;
    }

    @Bean
    public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
        return new FlywayMigrationInitializer(flyway, null);
    }

    /**
     * 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");
        }

    }
}

Ответ 3

Используя библиотеку Javassist, вы можете использовать библиотеку FlywayDB для регистрации того, что версия Oracle больше не поддерживается, вместо того, чтобы генерировать фатальное исключение (заключая вызов метода sureDatabaseIsCompatibleWithFlywayEdition в предложение try-catch). В моем случае редакция сообщества FlywayDB (5.2.4), кажется, прекрасно работает с Oracle 11.2, как только я это сделал. Это решение имеет свои недостатки, но в моем случае это был лучший вариант (база данных должна быть обновлена в ближайшее время), так что, возможно, кто-то найдет его полезным. Приведенный ниже код должен быть запущен в вашем приложении, прежде всего в идеале. Пожалуйста используйте на свой страх и риск.

public static void suppressIncompatibleDatabaseVersionCheck() {
    try {
        CtClass ctClass = ClassPool.getDefault().get("org.flywaydb.core.internal.database.base.Database");
        ctClass.defrost();
        CtMethod method = ctClass.getDeclaredMethod("ensureDatabaseIsCompatibleWithFlywayEdition");
        CtClass etype = ClassPool.getDefault().get("java.lang.Exception");
        method.addCatch("{ LOG.warn(\"Exception suppressed: \" + $e); return ;}", etype);
        ctClass.toClass();
    } catch (NotFoundException | CannotCompileException e) {
        log.error("Could not instrument FlywayDB code.", e);
    }
}

Ответ 4

Я согласен с вышеуказанными решениями. Но почему бы не перейти на последнюю зависимость от пролетного пути?

<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>5.2.4</version>
</dependency>

Это решит вашу проблему, так как FluentConfiguration является частью последней библиотеки от flyway-core.

Ответ 5

Используйте следующую зависимость, она будет разрешена этим.

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>5.2.3</version>
</dependency>