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初始化的空库。
解决步骤
统一连接字符串参数
将测试代码中的连接字符串修改为和Spring配置完全一致的版本:conn = DriverManager.getConnection("jdbc:h2:mem:myDB;DB_CLOSE_DELAY=-1;MODE=Oracle;IGNORECASE=TRUE","sa","123");确保所有参数完全匹配,才能连接到Flyway初始化过的同一个数据库实例。
使用Spring管理的数据库连接(推荐)
集成测试中避免手动通过DriverManager创建连接,直接注入Spring提供的DataSource或JdbcTemplate,保证和应用、Flyway使用同一个连接池:@Autowired private JdbcTemplate jdbcTemplate; // 测试方法中使用 String sql = "SELECT ..."; List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);确认Flyway执行时机
确保测试时加载完整Spring上下文(如使用@SpringBootTest注解),Flyway会在上下文启动时自动执行迁移脚本,完成表结构初始化。
内容的提问来源于stack exchange,提问作者Shabar
相关产品推荐
相关产品推荐

