知識庫 / Spring / Spring Boot RSS 訂閱

Spring Boot H2 JdbcSQLSyntaxErrorException 預期“標識符”

Persistence,Spring Boot
HongKong
6
11:35 AM · Dec 06 ,2025

1. 概述

本教程將深入探討異常 `org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement expected “identifier”.

首先,我們將闡明導致該異常的主要原因。然後,我們將通過一個實際示例演示如何重現該異常,最後,我們將提供解決方案。

2. 原因

在尋求解決方案之前,讓我們首先理解異常的原因。

通常,H2 會拋出 `JdbcSQLSyntaxErrorException 以指示 SQL 語句中的語法錯誤。因此,“expected identifier” 消息表明 SQL 期望一個合適的標識符,而我們未能提供。

最常見的原因是使用保留關鍵字作為標識符。

例如,使用關鍵字 <em >table</em > 來命名特定的 SQL 表將導致JdbcSQLSyntaxErrorException

另一個原因是 SQL 語句中的關鍵字缺失或位置錯誤。

3. 模擬異常

作為開發者,我們經常使用“user”這個詞來表示處理用户的數據表。不幸的是,它在 H2 中是一個 保留關鍵字

因此,為了模擬該異常,我們將假裝使用該關鍵字“user”。

因此,首先,讓我們添加一個基本的 SQL 腳本,用於初始化和填充 H2 數據庫中的數據:

INSERT INTO user VALUES (1, 'admin', 'p@ssw@rd'); 
INSERT INTO user VALUES (2, 'user', 'userpasswd');

接下來,我們將創建一個實體類來映射 user 表:

@Entity
public class User {

    @Id
    private int id;
    private String login;
    private String password;

    // standard getters and setters
}

請注意,@Entity 是一個 JPA 註解,用於標識一個類為實體類。

此外,@Id 表示映射數據庫中主鍵的字段。

現在,如果運行主應用程序,Spring Boot 將會報錯如下:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' 
...
nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "INSERT INTO [*]user VALUES (1, 'admin', 'p@ssw@rd')"; expected "identifier"; SQL statement:
INSERT INTO user VALUES (1, 'admin', 'p@ssw@rd') [42001-214]
...

正如日誌所示,H2 抱怨插入查詢是因為關鍵字 user 是一個關鍵字,不能用作標識符。

4. 解決方案

為了解決此異常,我們需要確保我們不使用 SQL 關鍵字作為標識符。

或者,我們可以使用分隔符來轉義它們。H2 支持雙引號作為標準標識符分隔符。

因此,首先讓我們用雙引號將關鍵字 user 包圍:

INSERT INTO "user" VALUES (1, 'admin', 'p@ssw@rd');
INSERT INTO "user" VALUES (2, 'user', 'userpasswd');

接下來,我們將為我們的實體 User 創建一個 JPA 存儲庫:

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
}

現在,讓我們添加一個測試用例,以確認一切都按預期工作:

@Test
public void givenValidInitData_whenCallingFindAll_thenReturnData() {
    List<User> users = userRepository.findAll();

    assertThat(users).hasSize(2);
}

如上所示,findAll() 能夠正常執行,不會拋出 JdbcSQLSyntaxErrorException 異常。

另一種避免該異常的方法是,在 JDBC URL 中添加 NON_KEYWORDS=user

spring.datasource.url=jdbc:h2:mem:mydb;NON_KEYWORDS=user

這樣一來,我們告訴 H2 將 user 關鍵詞從保留詞列表中排除

如果我們在使用 Hibernate,我們可以將 hibernate.globally_quoted_identifiers 屬性設置為 true

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

正如屬性名稱所示,Hibernate 將自動引用所有數據庫標識符。

因此,在使用 @Table@Column 註解時,我們無需手動轉義表名或列名。

簡而言之,以下是一些重要的注意事項:

  • 請確保使用正確的 SQL 關鍵字並將其放置在正確的順序中
  • 避免將保留關鍵字用作標識符
  • 仔細檢查任何不允許在 SQL 中使用的特殊字符
  • 請確保正確轉義或引用任何保留關鍵字

5. 結論

在本文中,我們詳細解釋了導致異常 <em >org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement expected “identifier”</em> 的原因。 此外,我們展示瞭如何產生該異常以及如何解決它。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.