You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flyway迁移H2失败求助:Spring Boot测试环境验证异常

解决Spring Boot测试环境Flyway验证失败问题

我之前也碰到过类似的情况,这个错误本质是Flyway检测到H2数据库的flyway_schema_history表中存在版本1的迁移失败记录,而根源大多是迁移脚本只适配了MySQL,在H2数据库上执行出错,或者测试环境的数据库残留了之前的失败历史。下面给你几个可行的解决步骤:

1. 让迁移脚本兼容MySQL和H2

MySQL和H2的SQL语法存在不少差异,比如MySQL的ENGINE=InnoDBCHARSET=utf8mb4,或者某些函数(比如NOW() vs CURRENT_TIMESTAMP())在H2里不兼容。你可以通过两种方式让脚本跨数据库兼容:

方式一:用数据库专属注释

在脚本中针对不同数据库写专属语法,H2会忽略MySQL的注释,MySQL会忽略H2的注释:

CREATE TABLE IF NOT EXISTS business_table (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
    /* MySQL */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    /* H2 */ ;
);

方式二:用Flyway占位符动态适配

在配置文件中添加数据库类型的占位符:

  • application-test.properties
    spring.flyway.placeholders.db_type=h2
    
  • application-prod.properties
    spring.flyway.placeholders.db_type=mysql
    

然后在迁移脚本中使用条件判断:

CREATE TABLE IF NOT EXISTS business_table (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
    ${if db_type='mysql'}ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;${endif}
    ${if db_type='h2'};${endif}
);

2. 清理测试环境的Flyway历史记录

因为之前迁移失败,H2数据库的flyway_schema_history表已经有了失败的记录,Flyway启动时会验证这些记录导致报错。你可以通过以下方式清理:

方式一:使用内存模式H2

把测试环境的H2改成内存模式,这样每次测试都会生成全新的数据库,彻底避免历史记录干扰。修改application-test.properties

spring.datasource.url=jdbc:h2:mem:my_db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

方式二:测试前自动清理数据库

利用flyway-spring-test的注解,在测试类上添加@FlywayTest(clean = true),确保每次测试前清理数据库:

@SpringBootTest
@ActiveProfiles("test")
@FlywayTest(clean = true)
public class YourApplicationTests {
    // 测试方法
}

方式三:临时允许Flyway清理

application-test.properties中添加:

spring.flyway.clean-disabled=false

注意:生产环境一定要把这个值设为true,避免误删生产数据!

3. 检查测试环境的Flyway配置

确认测试环境的Flyway配置是否正确:

  • 确保spring.flyway.schemas=PUBLIC和H2的默认schema一致;
  • 如果测试环境之前有手动创建的表,可以开启基线化:
    spring.flyway.baseline-on-migrate=true
    

按照上面的步骤调整后,应该就能解决H2测试环境的Flyway验证失败问题了。

内容的提问来源于stack exchange,提问作者Yasharzb

火山引擎 最新活动