You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot测试中H2无法识别Flyway刚迁移的表如何解决?

解决H2模拟PostgreSQL时Flyway迁移成功但Repository找不到表的问题

看起来你遇到的是表名大小写不匹配或者配置冲突导致的问题,我来分享几个排查方向和解决办法:

1. 先确认Flyway迁移的表是否真的存在,以及表名的大小写

虽然你说修改Flyway脚本会出现语法错误,但还是建议先验证H2里是否真的创建了目标表:

  • 在测试类里注入JdbcTemplate,执行SHOW TABLES查看所有表:
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Test
    public void debugTables() {
        List<String> tables = jdbcTemplate.queryForList("SHOW TABLES", String.class);
        System.out.println("当前H2中的表:" + tables);
    }
    
    看看输出里有没有MY_TABLE或者my_table——这会帮你定位是表没创建,还是大小写不匹配。

2. 修正H2连接URL的参数冲突

你的URL里同时设置了DATABASE_TO_UPPER=FALSE和DATABASE_TO_LOWER=TRUE,这两个参数是互斥的!H2文档明确说明不能同时启用,建议只保留DATABASE_TO_LOWER=TRUE,修改后的URL:

url: jdbc:h2:mem:test;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1

3. 对齐Flyway脚本、实体类和Hibernate的表名配置

这是最常见的问题:

情况A:Flyway脚本用无引号的大写表名

比如脚本里写:

CREATE TABLE MY_TABLE (
    id SERIAL PRIMARY KEY,
    ...
);

因为你设置了DATABASE_TO_LOWER=TRUE,H2会把表名转成小写my_table。这时候实体类的@Table注解要明确指定小写表名:

@Entity
@Table(name = "my_table") // 必须和H2中实际的表名一致
public class MyEntity {
    // ...
}

情况B:Flyway脚本用带引号的大写表名

如果脚本里是:

CREATE TABLE "MY_TABLE" (
    id SERIAL PRIMARY KEY,
    ...
);

PostgreSQL会保留大写表名,H2在MODE=PostgreSQL下也会保留。这时候实体类需要用引号包裹表名:

@Entity
@Table(name = "\"MY_TABLE\"") // 注意双引号的转义
public class MyEntity {
    // ...
}

4. 避免Hibernate和Flyway的DDL冲突

Flyway负责数据库迁移,一定要禁用Hibernate的自动DDL功能,否则Hibernate可能会重新创建表(导致表名不一致)。在配置里添加:

spring.jpa.hibernate.ddl-auto=none

5. 确认自定义数据源和EntityManagerFactory的正确性

你的配置类排除了DataSourceAutoConfiguration,自定义了数据源和EntityManagerFactory,要确保:

  • 自定义的数据源确实加载了H2的配置(可以在测试里打印数据源的URL验证);
  • EntityManagerFactory的Hibernate方言配置正确,建议用H2的PostgreSQL兼容方言:
    @Bean
    public LocalContainerEntityManagerFactoryBean customEntityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.example.myproj");
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect"); // 这里用H2方言即可,因为H2已经开启PostgreSQL模式
        em.setJpaVendorAdapter(vendorAdapter);
        // ... 其他配置
        return em;
    }
    

6. 验证Flyway在测试环境是否启用

确保测试环境的配置里没有禁用Flyway:

spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration # 确认迁移脚本的路径正确

按照上面的步骤逐一排查,应该能定位到问题所在。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:56:50