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,但看起来它支持以下内容:

  1. 2 个语句而不是同一个迁移中的一个语句(flyway 应该 运行 它们在同一个事务中):
ALTER TABLE task_def DROP COLUMN retry_count;
ALTER TABLE task_def DROP COLUMN timeout_seconds;
  1. 使用不同的语法:
ALTER TABLE task_def DROP COLUMN retry_count, timeout_seconds;

当然,如果 postgresql 允许的话。

总而言之,我不认为 H2 能够用它的方言涵盖 postgres 提供的所有功能,所以像这样的失败是不可避免的。

所以根据我的经验,以下方法效果更好:

创建一个 "test container" 的 postgres(参见 testcontainers 项目)并在测试中针对它配置 flyway / 数据源 运行。根据您的测试基础设施,您甚至可以不停止容器,而是在每个测试用例之前删除数据库和 运行 flyway。或者,您可以像在 spring 测试中那样做 - 在 运行 测试之前创建一个人工事务,并在测试完成时 "fail" 它(即使它成功完成),以便数据库获胜为下一次测试弄脏。