1. 引言
H2 是一款轻量级内存数据库,Spring Boot 可自动配置它,极大简化了数据访问逻辑的测试工作。
当出现 org.h2.jdbc.JdbcSQLSyntaxErrorException
异常时,通常意味着 SQL 语法存在问题。其中 "Table not found"
错误表明 H2 无法找到指定的表。
本文将演示如何复现并解决这个经典踩坑问题:JdbcSQLSyntaxErrorException: Table not found
。
2. 实践案例
2.1. H2 配置
Spring Boot 默认使用 sa
用户名和空密码连接 H2 数据库。在 application.properties
中添加以下配置:
spring.datasource.url=jdbc:h2:mem:mydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
假设我们有一个 person
表,通过 data.sql
初始化数据(Spring Boot 默认加载此文件):
INSERT INTO "person" VALUES (1, 'Abderrahim', 'Azhrioun');
INSERT INTO "person" VALUES (2, 'David', 'Smith');
INSERT INTO "person" VALUES (3, 'Jean', 'Anderson');
2.2. 对象关系映射
使用 JPA 注解 将 person
表映射为实体类:
@Entity
public class Person {
@Id
private int id;
@Column
private String firstName;
@Column
private String lastName;
// 标准getter/setter方法
}
关键注解说明:
@Entity
:声明该类为实体类,映射person
表@Id
:标记主键字段@Column
:绑定实体字段与数据库列
创建 JPA 仓库接口:
@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
}
Spring Data JPA 通过 JpaRepository
简化了数据操作。
启动应用后,控制台抛出异常:
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
...
at com.baeldung.h2.tablenotfound.TableNotFoundExceptionApplication.main(TableNotFoundExceptionApplication.java:10)
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "person" not found (this database is empty); SQL statement:
...
⚠️ 问题根源:data.sql
脚本在 Hibernate 初始化前执行,导致表尚未创建就被访问。这是 Spring Boot 2.5+ 的默认行为,旨在与 Liquibase 和 Flyway 等迁移工具保持一致。
3. 解决方案
在 application.properties
中添加配置即可解决:
spring.jpa.defer-datasource-initialization=true
✅ 作用原理:该属性将数据初始化操作推迟到 Hibernate 完成表结构创建之后执行。
验证修复效果的测试用例:
@SpringBootTest(classes = TableNotFoundExceptionApplication.class)
class TableNotFoundExceptionIntegrationTest {
@Autowired
private PersonRepository personRepository;
@Test
void givenValidInitData_whenCallingFindAll_thenReturnData() {
assertEquals(3, personRepository.findAll().size());
}
}
测试顺利通过,确认问题已解决。
4. 总结
本文分析了 H2 数据库抛出 JdbcSQLSyntaxErrorException: Table not found
的根本原因,演示了复现过程,并提供了简单粗暴的解决方案。核心要点:
- 问题本质:数据初始化脚本早于 Hibernate 执行
- 解决方案:启用
spring.jpa.defer-datasource-initialization
延迟初始化 - 适用场景:Spring Boot 2.5+ 版本使用 H2 内存数据库时
完整示例代码可在 GitHub 获取。