我正在尝试在 Docker 容器中运行我的项目测试。所有测试在本地运行时都运行良好。当我尝试将测试转移到 docker 容器时,错误开始发生。 这是错误消息:
java.lang.IllegalStateException: Failed to load ApplicationContext
[...]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V1__initial_user.sql failed
-------------------------------------
SQL State : 42601
Error Code : 0
Message : ERROR: syntax error at or near "GENERATED"
Position: 45
Location : db/migration/V1__initial_user.sql (/Users/villemossip/Desktop/GRP/GRP-SAS/application/build/resources/main/db/migration/V1__initial_user.sql)
Line : 36
Statement : CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
)
从日志中我们可以看到容器镜像已创建,但未能迁移sql schema:
[...]
2019-10-10 10:36:18.768 INFO 49547 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse
2019-10-10 10:36:18.777 INFO 49547 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-10-10 10:36:18.795 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Creating container for image: postgres:9.6.12
2019-10-10 10:36:19.001 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Starting container with ID: a32dd0850baf34770cce9bdc81918cd4db40502188b85dfaa90f74e2900f9fa7
2019-10-10 10:36:19.547 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Container postgres:9.6.12 is starting: a32dd0850baf34770cce9bdc81918cd4db40502188b85dfaa90f74e2900f9fa7
2019-10-10 10:36:23.342 INFO 49547 --- [ main] 🐳 [postgres:9.6.12] : Container postgres:9.6.12 started
2019-10-10 10:36:23.426 INFO 49547 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-10-10 10:36:23.431 INFO 49547 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:postgresql://localhost:32834/test (PostgreSQL 9.6)
2019-10-10 10:36:23.488 INFO 49547 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 6 migrations (execution time 00:00.024s)
2019-10-10 10:36:23.501 INFO 49547 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: "public"."flyway_schema_history"
2019-10-10 10:36:23.519 INFO 49547 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "public": << Empty Schema >>
2019-10-10 10:36:23.520 INFO 49547 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema "public" to version 1 - initial user
2019-10-10 10:36:23.542 ERROR 49547 --- [ main] o.f.core.internal.command.DbMigrate : Migration of schema "public" to version 1 - initial user failed! Changes successfully rolled back.
2019-10-10 10:36:23.546 WARN 49547 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V1__initial_user.sql failed
-------------------------------------
[...]
这是sql脚本的一部分(app/src/main/resources/db/migration):
[...]
constraint user_aud_pkey primary key (id, rev)
);
CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
);
CREATE SEQUENCE hibernate_sequence INCREMENT 1 MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
这是“application.properties”(应用程序/测试/java/资源):
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:postgresql://localhost:5433/test
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
spring.jackson.default-property-inclusion=NON_NULL
spring.flyway.baselineOnMigrate=true
spring.flyway.check-location=true
spring.flyway.locations=classpath:db/migration
spring.flyway.schemas=public
spring.flyway.enabled=true
还在同一目录中我有container-license-acceptance.txt 文件。
在“build.gradle”内我添加了以下几行(app/build.gradle):
dependencies {
[...]
testImplementation "org.testcontainers:junit-jupiter:1.11.3"
testImplementation "org.testcontainers:postgresql:1.11.3"
}
在 BaseInitTest 文件内,我有以下几行(app/test/java/com):
@Testcontainers
@SpringBootTest
public class BaseIntTest {
@Container
private static final PostgreSQLContainer<?> container = new PostgreSQLContainer<>();
[...]
我不明白,为什么同样的测试一开始会通过,但当我将它们移动到 docker 容器时却失败?
看起来带有数据库的测试容器已成功启动,所以没有问题,您得到的是一个空数据库。
然后你尝试运行飞行路线,但失败了。 Spring Boot中的Flyway在Spring应用程序上下文初始化期间工作, 因此,实际的迁移在应用程序上下文初始化时运行,因此迁移失败看起来像 spring 失败。
但是,记录了原因:迁移文件包含无效内容:
Migration V1__initial_user.sql failed
-------------------------------------
SQL State : 42601
Error Code : 0
Message : ERROR: syntax error at or near "GENERATED"
Position: 45
Location : db/migration/V1__initial_user.sql (/Users/villemossip/Desktop/GRP/GRP-
SAS/application/build/resources/main/db/migration/V1__initial_user.sql)
Line : 36
Statement : CREATE TABLE revinfo
(
rev INTEGER GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ),
revtstmp BIGINT,
PRIMARY KEY (rev)
)
这个
GENERATED BY
不受支持。
为什么?您的 docker 映像可能包含不支持此语法的 RDBMS 版本。所以它和你在没有docker的本地环境中使用的DB不同。
无论如何,这不是关于 docker、spring 或 Flyway 的问题,而是关于数据库和迁移代码的问题。
在分辨率方面,我建议直接运行DB的docker镜像(不带java、testcontainers和flyway)。 当它运行时,只需在 pgadmin 或其他东西中“手动”运行此迁移即可。您预计会看到相同的错误。
谢谢你@M。 Deinum 和 Mark Bramnik!
我发现问题出在 Postgres 版本上。由于某种原因,默认情况下,docker 映像是使用旧版本 9.6.12 创建的,但 sql 脚本GENERATED BY DEFAULT已添加到版本 10 的 Postgres 中。
解决方案1(将sql脚本更新到旧版本):
CREATE TABLE revinfo
(
rev INTEGER PRIMARY KEY NOT NULL,
revtstmp BIGINT
);
解决方案2: 通过在项目中创建 CustomPostgreSQLContainer 文件将 docker 镜像版本更改为 11.2。
import org.testcontainers.containers.PostgreSQLContainer;
public class CustomPostgreSQLContainer extends PostgreSQLContainer<CustomPostgreSQLContainer> {
private static final String IMAGE_VERSION = "postgres:11.2";
private static CustomPostgreSQLContainer container;
CustomPostgreSQLContainer() {
super(IMAGE_VERSION);
}
public static CustomPostgreSQLContainer getInstance() {
if (container == null) {
container = new CustomPostgreSQLContainer();
}
return container;
}
@Override
public void start() {
super.start();
System.setProperty("spring.datasource.url", container.getJdbcUrl());
System.setProperty("spring.datasource.username", container.getUsername());
System.setProperty("spring.datasource.password", container.getPassword());
}
@Override
public void stop() {
//do nothing, JVM handles shut down
}
}
并更新 BaseIntTest 文件:
@Testcontainers
@SpringBootTest
public class BaseIntTest {
@Container
private static final PostgreSQLContainer<?> container = CustomPostgreSQLContainer.getInstance();
最后从测试 application.properties 文件中删除两行:
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:postgresql://localhost:5433/test
就我而言,我在 application.properties 文件中添加了
spring.flyway.baselineOnMigrate = true
我还必须从版本 1.1 而不是 1 开始,否则 Flyway 会抛出错误(flyway 8.0.5)
此问题的一个原因是缺少 docker DB 版本:
通过添加这个特定版本,它对我有用。
如前所述,
GENERATED BY DEFAUL
需要更新版本的 postgres 映像。在您的情况下,postgres 映像默认为 9.6.12。
简单的解决方案是更新
application.properties
中的数据源 url 并指向那里的较新的 postgres 图像。
spring.datasource.url=jdbc:tc:postgresql:11.2://localhost:5433/test
我的情况的问题是因为使用
spring.datasource.url=jdbc:postgres://localhost:5432/todoListDb
而不是
spring.datasource.url=jdbc:postgresql://localhost:5432/todoListDb
(postgres 而不是 PostgreSQL)在我的 application.properties 文件中
因此请尝试为您的数据库使用正确的 URL,并验证您的 url 中是否存在拼写错误
就我而言:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'flywayInitializer' defined in class path resource
[org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]:
Unsupported Database: MySQL 8.4
我所要做的就是替换
build.gradle
依赖项行:
implementation 'org.flywaydb:flyway-core'
与:
implementation 'org.flywaydb:flyway-mysql'
礼貌:https://documentation.red-gate.com/flyway/flyway-cli-and-api/supported-databases/mysql