51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

解决 Spring Boot H2 JdbcSQLSyntaxErrorException “Table not found”

1、简介 {#1简介}

H2 是一个简单的轻量级内存数据库,Spring Boot 可以自动对其进行配置,使开发人员可以轻松测试数据访问逻辑。

通常情况下,org.h2.jdbc.JdbcSQLSyntaxErrorException 是用于表示与 SQL 语法相关的错误的异常。"Table not found" 表示 H2 无法找到指定的表。

本文将带你了解 H2 抛出 JdbcSQLSyntaxErrorException 异常的原因以及解决办法。

2、示例 {#2示例}

既然知道了异常背后的根本原因,来看看如何重现异常。

2.1、H2 配置 {#21h2-配置}

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 的表。在此,使用一个基本的 SQL 脚本为数据库添加数据。默认情况下,Spring Boot 会加载 data.sql 文件:

INSERT INTO "person" VALUES (1, 'Abderrahim', 'Azhrioun');
INSERT INTO "person" VALUES (2, 'David', 'Smith');
INSERT INTO "person" VALUES (3, 'Jean', 'Anderson');

2.2、对象关系映射 {#22对象关系映射}

接下来,使用 JPA 注解将表 person 映射到一个实体。

Person 实体如下:

@Entity
public class Person {

    @Id
    private int id;
    @Column
    private String firstName;
    @Column
    private String lastName;

    // Getter/Setter 方法省略

}

@Entity 注解表明该类是一个映射 person 表的实体。此外,@Id 表示 id 属性代表主键,@Column 注解将表列绑定到实体字段。

接下来,为实体 Person 创建一个 JPA Repository:

@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
}

Spring Data JPA 提供了 JpaRepository 接口,以简化存储和检索数据的逻辑。

现在,尝试启动 Spring Boot 应用,看看会发生什么。查看日志,可以发现应用在启动时出现了 org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "person" not found 异常:

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 初始化之前执行的。这就是为什么 Hibernate 找不到表 person 的原因。

通常,这是为了将基于脚本的初始化行为与其他数据库迁移工具(如 LiquibaseFlyway)保持一致而设定的默认行为。

3、解决办法 {#3解决办法}

幸运的是,Spring Boot 提供了解决这一限制的快捷方法。只需在 application.properties 中将 spring.jpa.defer-datasource-initialization 属性设置为 true,即可避免异常:

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、总结 {#4总结}

本文介绍了了导致 H2 抛出 "JdbcSQLSyntaxErrorException: Table not found" 的原因以及解决办法。


Ref:https://www.baeldung.com/spring-boot-h2-jdbcsqlsyntaxerrorexception-table-not-found

赞(1)
未经允许不得转载:工具盒子 » 解决 Spring Boot H2 JdbcSQLSyntaxErrorException “Table not found”