Spring Boot集成测试:H2模拟PostgreSQL+Flyway加载初始数据失败
解决H2模拟PostgreSQL+Flyway加载初始数据时的连接拒绝问题
问题场景
做集成测试时需要用H2模拟PostgreSQL,结合Flyway加载初始数据,但运行时直接报错连接localhost:5432被拒绝,相关配置和报错信息如下:
配置文件
build.gradle
implementation 'org.flywaydb:flyway-core:9.19.1' implementation 'org.postgresql:postgresql:42.6.0' ... runtimeOnly 'com.h2database:h2:2.1.214'
application-dev.properties
#1st approach #spring.datasource.url=jdbc:postgresql://localhost:5432/configdb #spring.datasource.driverClassName=org.postgresql.Driver #spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL8Dialect #2nd approach spring.datasource.url=jdbc:h2:mem:configdb;DB_CLOSE_DELAY=-1;MODE=PostgreSQL spring.datasource.driverClassName=org.h2.Driver spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=none spring.flyway.schemas=config spring.flyway.locations=classpath:db
项目根目录flyway.conf
flyway.user=postgres flyway.password=postgres flyway.schemas=config #flyway.url=jdbc:postgresql://localhost:5432/configdb flyway.url=jdbc:h2:mem:configdb flyway.locations=classpath:db
resources/db/V1__CreateConfigTable.sql
CREATE TABLE configdb.config ( id bigint PRIMARY KEY, ... ); -- INSERT query
报错信息
Caused by: org.flywaydb.core.internal.exception.FlywaySqlException: Unable to obtain connection from database: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
问题根源
- 配置冲突:Spring Boot中Flyway的配置优先级可能被其他配置源覆盖,比如独立的
flyway.conf和application-dev.properties不一致,或系统环境变量残留PostgreSQL连接信息,导致Flyway误用错误连接。 - H2配置不完整:仅设置
MODE=PostgreSQL但缺少兼容参数,且JPA使用H2方言,导致SQL解析行为和PostgreSQL不一致。 - SQL脚本表名错误:脚本中写的
configdb.config与指定的Flyway schemaconfig不匹配,H2中不存在configdb库,执行脚本失败后Flyway可能 fallback 到旧的PostgreSQL配置。 - Flyway未绑定Spring数据源:Flyway可能未使用Spring配置的H2数据源,而是自行加载了旧的PostgreSQL连接配置。
修复步骤
1. 统一Flyway与Spring数据源配置
直接在application-dev.properties中绑定Flyway和Spring数据源,避免独立配置文件的冲突:
# 补全H2兼容PostgreSQL的参数 spring.datasource.url=jdbc:h2:mem:configdb;DB_CLOSE_DELAY=-1;MODE=PostgreSQL;DATABASE_TO_UPPER=false spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=postgres spring.datasource.password=postgres # JPA改用PostgreSQL方言,提升H2模拟准确性 spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=none # Flyway绑定Spring数据源,确保使用同一份连接配置 spring.flyway.enabled=true spring.flyway.schemas=config spring.flyway.locations=classpath:db spring.flyway.url=${spring.datasource.url} spring.flyway.user=${spring.datasource.username} spring.flyway.password=${spring.datasource.password}
加
DATABASE_TO_UPPER=false是为了让H2不自动将表名转为大写,和PostgreSQL保持一致;切换PostgreSQL方言能让JPA生成的SQL更贴合PostgreSQL语法。
2. 删除或同步flyway.conf
要么直接删除项目根目录的flyway.conf,让Flyway完全依赖Spring配置;如果必须保留,需将其中的配置与application-dev.properties完全同步,避免冲突。
3. 修正SQL脚本的表名
脚本中的configdb.config不符合指定的schema,调整为config schema,并预先创建schema防止报错:
-- 先创建schema,确保存在 CREATE SCHEMA IF NOT EXISTS config; CREATE TABLE config.config ( id bigint PRIMARY KEY, ... ); -- INSERT query
4. 确保启动时使用dev配置
启动应用时必须添加spring.profiles.active=dev参数,否则会加载默认配置,可能又切换到PostgreSQL连接。
5. 调整PostgreSQL依赖范围
将postgresql依赖改为runtimeOnly,避免测试环境下优先加载PostgreSQL驱动,干扰H2的使用:
implementation 'org.flywaydb:flyway-core:9.19.1' runtimeOnly 'org.postgresql:postgresql:42.6.0' ... runtimeOnly 'com.h2database:h2:2.1.214'
验证
启动后查看Flyway日志,若显示成功执行迁移脚本;开启H2控制台后能看到config schema及对应表,即说明问题解决。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

