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

Spring Boot集成测试执行H2 SELECT查询报错:表不存在(数据库为空)

H2内存数据库集成测试表找不到问题排查

在Spring Boot集成测试执行SELECT语句时抛出如下错误:

org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "MY_TABLE1" not found (this database is empty); SQL statement:
    SELECT PHD.ID, PRS.ID, PHD.*, PDT.*, PRS.*, PAD.* FROM MY_TABLE1 PHD JOIN MY_TABLE2 PRS ON PHD.REFERENCE_ID = PRS.REFERENCE_ID JOIN MY_TABLE3 PDT ON PDT.HEADER_ID = PHD.ID JOIN MY_TABLE4 PAD ON PAD.MY_HEADER_ID = PHD.ID AND PHD.REFERENCE_ID IN ('ABC6317000802') ORDER BY PHD.CREATED_TS, PDT.CREATED_TS, PRS.CREATED_TS, PAD.CREATED_TS, PAD.ID ASC [42104-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:502)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
    at org.h2.message.DbException.get(DbException.java:223)
    at org.h2.message.DbException.get(DbException.java:199)
    at org.h2.command.Parser.getTableOrViewNotFoundDbException(Parser.java:8385)
    at org.h2.command.Parser.getTableOrViewNotFoundDbException(Parser.java:8369)
    at org.h2.command.Parser.readTableOrView(Parser.java:8358)
    at org.h2.command.Parser.readTablePrimary(Parser.java:1863)
    at org.h2.command.Parser.readTableReference(Parser.java:2334)
    at org.h2.command.Parser.parseSelectFromPart(Parser.java:2772)
    at org.h2.command.Parser.parseSelect(Parser.java:2878)
    at org.h2.command.Parser.parseQueryPrimary(Parser.java:2762)
    at org.h2.command.Parser.parseQueryTerm(Parser.java:2633)
    at org.h2.command.Parser.parseQueryExpressionBody(Parser.java:2612)
    at org.h2.command.Parser.parseQueryExpressionBodyAndEndOfQuery(Parser.java:2605)
    at org.h2.command.Parser.parseQueryExpression(Parser.java:2598)
    at org.h2.command.Parser.parseQuery(Parser.java:2567)
    at org.h2.command.Parser.parsePrepared(Parser.java:724)
    at org.h2.command.Parser.parse(Parser.java:689)
    at org.h2.command.Parser.parse(Parser.java:661)
    at org.h2.command.Parser.prepareCommand(Parser.java:569)
    at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631)
    at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554)
    at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116)
    at org.h2.jdbc.JdbcStatement.executeQuery(JdbcStatement.java:92)

现象说明

  • 应用启动无异常,H2控制台能查看所有表,相同SQL在控制台执行可正常返回结果
  • 已尝试常见解决方案但未解决

应用配置(application.yaml)

spring:
  cache:
    enabled: false

  datasource:
    url: jdbc:h2:mem:myDB;DB_CLOSE_DELAY=-1;MODE=Oracle;IGNORECASE=TRUE 
    username: sa
    password: 123
    driverClassName: org.h2.Driver
 
  flyway:
    enabled: true
    username: sa
    password: 123
    url: jdbc:h2:mem:myDB;DB_CLOSE_DELAY=-1;MODE=Oracle
    baseline-on-migrate: true
    locations: filesystem:C:\Repo\MyAPII\api\src\integrationTest

  h2:
    console:
      enabled: true
      path: /h2-console

测试用查询代码

Connection conn = null; 
Statement stmt = null; 
try { 
   Class.forName(JDBC_DRIVER);  
   conn = DriverManager.getConnection("h2:mem:myDB","sa","123");  

stmt = conn.createStatement(); 
String sql = "SELECT PHD.ID, PRS.ID, PHD.*, PDT.*, PRS.*, PAD.*...."; 
ResultSet rs = stmt.executeQuery(sql);

String metadataValue = "";
String strMetadata = "Status";
String intMetadata = 1;

while (rs.next()) {
    metadataValue = strMetadata.isEmpty() || strMetadata.isBlank() ? rs.getString(intMetadata) : rs.getString(strMetadata);
}
statement.close();
conn.close();

问题根源与解决方法

核心问题:连接字符串不匹配导致连接全新空数据库

H2内存数据库会根据完整连接字符串识别不同实例,哪怕数据库名相同,只要连接参数(如MODE=Oracle、IGNORECASE=TRUE)不一致,就会创建新的空数据库。你的测试代码使用的连接字符串缺少配置中的关键参数,导致连接到未被Flyway初始化的空库。

解决步骤

  1. 统一连接字符串参数
    将测试代码中的连接字符串修改为和Spring配置完全一致的版本:

    conn = DriverManager.getConnection("jdbc:h2:mem:myDB;DB_CLOSE_DELAY=-1;MODE=Oracle;IGNORECASE=TRUE","sa","123");
    

    确保所有参数完全匹配,才能连接到Flyway初始化过的同一个数据库实例。

  2. 使用Spring管理的数据库连接(推荐)
    集成测试中避免手动通过DriverManager创建连接,直接注入Spring提供的DataSource或JdbcTemplate,保证和应用、Flyway使用同一个连接池:

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 测试方法中使用
    String sql = "SELECT ...";
    List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
    
  3. 确认Flyway执行时机
    确保测试时加载完整Spring上下文(如使用@SpringBootTest注解),Flyway会在上下文启动时自动执行迁移脚本,完成表结构初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:32:27