Flyway h2 postgressql 模式迁移不起作用
Flyway h2 postgressql mode migration not working
我必须遵循在 postgres 中工作的迁移:
ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds;
(和产品中的 运行)
但现在我想切换到 h2 进行单元测试,但 h2 似乎不接受它
spring 启动时我的数据库配置:
spring.datasource.url=jdbc:h2:./target/testdb;MODE=PostgreSQL
spring.datasource.username="sa"
spring.datasource.password=""
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driver-class-name=org.postgresql.Driver
spring.flyway.url=jdbc:h2:./target/testdb;MODE=PostgreSQL
spring.flyway.user="sa"
spring.flyway.password=""
spring.flyway.schemas=
错误:
Migration V3__.....sql failed
---------------------------------------
SQL State : 42S22
Error Code : 42122
Message : Column "DROP" not found; SQL statement:
ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds [42122-200]
Location : db/migration/V3__.....sql
Line : 1
Statement : ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds
没有可移植的方式一次删除多列,ALTER TABLE … DROP COLUMN
是一个标准命令,但只针对一列。
但是,有些数据库,包括 PostgreSQL 和 H2,支持这种非标准特性,但它们的语法不同。 PostgreSQL 预计
ALTER TABLE tableName DROP COLUMN columnName1, DROP COLUMN columnName2, …
https://www.postgresql.org/docs/12/sql-altertable.html
H2 预期
ALTER TABLE tableName DROP COLUMN columnName1, columnName2, …
https://h2database.com/html/commands.html#alter_table_drop_column
如果您使用不同的数据库,您应该尽可能避免不可移植的命令。
我没有使用过 H2,但看起来它支持以下内容:
- 2 个语句而不是同一个迁移中的一个语句(flyway 应该 运行 它们在同一个事务中):
ALTER TABLE task_def DROP COLUMN retry_count;
ALTER TABLE task_def DROP COLUMN timeout_seconds;
- 使用不同的语法:
ALTER TABLE task_def DROP COLUMN retry_count, timeout_seconds;
当然,如果 postgresql 允许的话。
总而言之,我不认为 H2 能够用它的方言涵盖 postgres 提供的所有功能,所以像这样的失败是不可避免的。
所以根据我的经验,以下方法效果更好:
创建一个 "test container" 的 postgres(参见 testcontainers 项目)并在测试中针对它配置 flyway / 数据源 运行。根据您的测试基础设施,您甚至可以不停止容器,而是在每个测试用例之前删除数据库和 运行 flyway。或者,您可以像在 spring 测试中那样做 - 在 运行 测试之前创建一个人工事务,并在测试完成时 "fail" 它(即使它成功完成),以便数据库获胜为下一次测试弄脏。
我必须遵循在 postgres 中工作的迁移:
ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds;
(和产品中的 运行) 但现在我想切换到 h2 进行单元测试,但 h2 似乎不接受它 spring 启动时我的数据库配置:
spring.datasource.url=jdbc:h2:./target/testdb;MODE=PostgreSQL
spring.datasource.username="sa"
spring.datasource.password=""
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driver-class-name=org.postgresql.Driver
spring.flyway.url=jdbc:h2:./target/testdb;MODE=PostgreSQL
spring.flyway.user="sa"
spring.flyway.password=""
spring.flyway.schemas=
错误:
Migration V3__.....sql failed
---------------------------------------
SQL State : 42S22
Error Code : 42122
Message : Column "DROP" not found; SQL statement:
ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds [42122-200]
Location : db/migration/V3__.....sql
Line : 1
Statement : ALTER TABLE task_def
DROP COLUMN retry_count,
DROP COLUMN timeout_seconds
没有可移植的方式一次删除多列,ALTER TABLE … DROP COLUMN
是一个标准命令,但只针对一列。
但是,有些数据库,包括 PostgreSQL 和 H2,支持这种非标准特性,但它们的语法不同。 PostgreSQL 预计
ALTER TABLE tableName DROP COLUMN columnName1, DROP COLUMN columnName2, …
https://www.postgresql.org/docs/12/sql-altertable.html
H2 预期
ALTER TABLE tableName DROP COLUMN columnName1, columnName2, …
https://h2database.com/html/commands.html#alter_table_drop_column
如果您使用不同的数据库,您应该尽可能避免不可移植的命令。
我没有使用过 H2,但看起来它支持以下内容:
- 2 个语句而不是同一个迁移中的一个语句(flyway 应该 运行 它们在同一个事务中):
ALTER TABLE task_def DROP COLUMN retry_count;
ALTER TABLE task_def DROP COLUMN timeout_seconds;
- 使用不同的语法:
ALTER TABLE task_def DROP COLUMN retry_count, timeout_seconds;
当然,如果 postgresql 允许的话。
总而言之,我不认为 H2 能够用它的方言涵盖 postgres 提供的所有功能,所以像这样的失败是不可避免的。
所以根据我的经验,以下方法效果更好:
创建一个 "test container" 的 postgres(参见 testcontainers 项目)并在测试中针对它配置 flyway / 数据源 运行。根据您的测试基础设施,您甚至可以不停止容器,而是在每个测试用例之前删除数据库和 运行 flyway。或者,您可以像在 spring 测试中那样做 - 在 运行 测试之前创建一个人工事务,并在测试完成时 "fail" 它(即使它成功完成),以便数据库获胜为下一次测试弄脏。