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
的原因。
通常,这是为了将基于脚本的初始化行为与其他数据库迁移工具(如 Liquibase 和 Flyway)保持一致而设定的默认行为。
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