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+ 的默认行为,旨在与 LiquibaseFlyway 等迁移工具保持一致。

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 的根本原因,演示了复现过程,并提供了简单粗暴的解决方案。核心要点:

  1. 问题本质:数据初始化脚本早于 Hibernate 执行
  2. 解决方案:启用 spring.jpa.defer-datasource-initialization 延迟初始化
  3. 适用场景:Spring Boot 2.5+ 版本使用 H2 内存数据库时

完整示例代码可在 GitHub 获取。


原始标题:Fix Spring Boot H2 JdbcSQLSyntaxErrorException “Table not found” | Baeldung