1. 概述
在这个简短的教程中,我们将仔细研究异常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', '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:
@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”背后的原因。然后,我们展示了如何产生异常以及如何修复它。
Post Directory
