Я хотел бы обновить свои новые проекты до Spring Boot версии 2.1.0, но я ограничен базой данных Oracle 11, которая поддерживается библиотекой Пролетной путь 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;
}
Да, заметил, но нельзя ли как-то исключить его в pom.xml в пользу более старого? Я мог найти правильную зависимость, но он искал этот класс FluentConfiguration.
Конечно можно. Но это не изменит код загрузки Spring, который настраивает Flyway и использует новые классы, существующие только в последней версии Flyway. Чтобы провести аналогию, если вы скомпилируете классы, которые используют java.util.stream с Java 8, а затем попытаетесь запустить этот код на Java 7, это не сработает, потому что java.util.stream не существует в Java 7. .
как вам удалось протестировать свое приложение?




У меня была такая же проблема с 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: это код Kotlin, но вы сможете довольно легко перевести его на Java.
Привет. Да, это именно то, что я пытался сделать, пожалуйста, посмотрите мой комментарий; Произведите конфигурацию программно. Дело в том, что это правильный путь? Почему автоконфигурация была изменена таким образом? И как тогда настроить разные источники данных для разных сред, если я не могу использовать application.properties? Спасибо
Вы можете использовать application.properties. Просто не ожидайте, что свойства flyway будут иметь какой-либо эффект, поскольку Spring Boot больше не будет их читать и применять. Остальные, не связанные с Flyway, по-прежнему будут работать.
Как заставить его работать в тестах Spring Boot? Мне нужно загрузить различные свойства для flyway для тестов, но либо компонент Flyway недоступен, либо когда я создаю bean-компонент Flyway вручную, другие компоненты теряются. Спасибо
@JBNizet Как человек, не знающий Kotlin, все понятно, кроме последней строчки.
@Younes_EO Последняя строка: `@Configuration общедоступный статический класс FlywayInitializerJpaDependencyConfiguration extends EntityManagerFactoryDependsOnPostProcessor {public FlywayInitializerJpaDependencyConfiguration () {super (" flywayInitializer "); }} `
Я сделал конфигурацию для Spring Boot 2.1.1, и мне также пришлось переопределить bean-компонент 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");
}
}
}
вы можете использовать его в @SpringBootTest?
Да, сама перезаписанная конфигурация работает с @SpringBootTest. Но обычно ты не понимаешь смысла использовать t want to use Oracle database for integration test, so I don только для теста. Я использую базу данных H2 для @SpringBootTest, и у нее нет проблем с последней версией Flyway. Хотя для совместимости я не создавал собственную конфигурацию Flyway для интеграционного теста.
Да, это то, что я хочу сделать, но почему-то не могу придумать правильный путь. Если я включаю application.yml в test / resource, создается экземпляр компонента Flyway Bean, и он создается для версии 5+. Если я где-то помещу @ Configuration или @ TestCOnfiguration, я могу создать его программно, но тогда другие Bean (Daos, Services) будут нулевыми, потому что мне также нужно создать их вручную. Я просто хочу создать Flyway Bean вручную, а все остальное оставлю на Spring.
Пришлось добавить spring.main.allow-bean-definition-overriding=true в application.properties, но он работает!
Используя библиотеку 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);
}
}
Используйте следующую зависимость, этим она будет решена.
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.3</version>
</dependency>
Как я уже упоминал в вопросе, я не могу использовать более высокую версию flyway, чем 4.2.0, из-за неподдерживаемого Oracle 11
То же самое для меня не могу использовать более высокую версию flyway, если вы не скажете, что flyway-core 5 совместим с ojdbc6 11 и oracle 11 (что не так)
Это вообще не ошибка. Spring Boot зависит от Flyway 5.2.1, API которого отличается от используемой вами старой версии.