Spring Boot H2 JdbcSQLSyntaxErrorException 預期為“標識符”
一、概述
在這個簡短的教程中,我們將仔細研究異常org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement expected “identifier”.
首先,我們將從闡明異常的主要原因開始。然後,我們將使用一個實際示例來說明如何重現它,最後說明如何解決它。
2. 原因
在跳轉到解決方案之前,讓我們先了解異常。
通常,H2 拋出JdbcSQLSyntaxErrorException
以表示 SQL 語句中的語法錯誤。因此, “expected identifier”
消息表示 SQL 需要一個合適的標識符,而我們沒有給出。
此異常的最常見原因是使用保留關鍵字作為標識符。
例如,使用關鍵字table
來命名特定的 SQL 表將導致JdbcSQLSyntaxErrorException.
另一個原因是 SQL 語句中的關鍵字丟失或錯放。
3.重現異常
作為開發人員,我們經常使用“ user”
一詞來表示處理用戶的表。不幸的是,它是 H2 中的保留關鍵字。
因此,為了重現異常,我們將假裝使用關鍵字“ user”.
因此,首先,讓我們添加一個基本的 SQL 腳本來初始化 H2 數據庫並使用數據播種:
INSERT INTO user VALUES (1, 'admin', '[email protected]@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', '[email protected]@rd')"; expected "identifier"; SQL statement:
INSERT INTO user VALUES (1, 'admin', '[email protected]@rd') [42001-214]
...
正如我們在日誌中看到的,H2 抱怨插入查詢,因為關鍵字user
是保留的,不能用作標識符。
4.解決方案
要修復異常,我們需要確保我們沒有使用 SQL 保留關鍵字作為標識符。
或者,我們可以使用定界符轉義它們。 H2 支持雙引號作為標準標識符分隔符。
所以首先,讓我們雙引號關鍵字user
:
INSERT INTO "user" VALUES (1, 'admin', '[email protected]@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.
避免異常的另一種解決方法是將NON_KEYWORDS=user
附加到 JDBC URL:
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.結論
在這篇簡短的文章中,我們詳細解釋了異常org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement expected “identifier”
背後的原因。然後,我們展示瞭如何產生異常以及如何修復它。
與往常一樣,示例的完整源代碼可在 GitHub 上獲得。