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
相关产品推荐
相关产品推荐

