Spring-Boot-Data-JPA使用H2数据库为什么无法创建表名为User的表?User是H2数据库的关键字吗?

作者站长头像
站长
· 阅读数 15

问题描述

开发时使用Spring-Boot-Data-JPA操作H2数据库,创建表名为User的表失败H2中用于保存用户的表是Users,表名应该没有冲突,User是H2数据库的关键字吗?JPA生成的SQL代码中被@Id注释的username字段没有被指定为identifier,但是仅更改表名后可以就正常创建,其他表也都没有这个问题

问题出现的环境背景及自己尝试过哪些方法

Spring-Boot 2.7.11Spring-Boot-Data-JPAH2数据库Eclipse + Spring Tools

相关代码

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
public class User {
    
    @Id
    private String username;
    
    private String password;
}

你期待的结果是什么?实际看到的错误信息又是什么?

期待的结果是正常创建User表,但实际会报错报错如下(有省略)

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "drop table if exists user CASCADE " via JDBC Statement

…

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "drop table if exists [*]user CASCADE "; expected "identifier"; SQL statement:
drop table if exists user CASCADE  [42001-214]

…

2023-04-24 15:04:27.375  WARN 10816 --- [  restartedMain] o.h.t.s.i.ExceptionHandlerLoggedImpl     : GenerationTarget encountered exception accepting command : Error executing DDL "create table user (username varchar(255) not null, password varchar(255), primary key (username))" via JDBC Statement

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table user (username varchar(255) not null, password varchar(255), primary key (username))" via JDBC Statement

…

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "create table [*]user (username varchar(255) not null, password varchar(255), primary key (username))"; expected "identifier"; SQL statement:
create table user (username varchar(255) not null, password varchar(255), primary key (username)) [42001-214]
回复
1个回答
avatar
test
2024-07-05

来自H2官方文档:H2的关键字里面明确说明:There is a list of keywords that can't be used as identifiers (table names, column names and so on), unless they are quoted (surrounded with double quotes).下面是不能用作标识符的关键字列表(表名、列名等),除非它们被引号(用双引号括起来)。answer image给出的列表里面就包括了user,所以尝试在你建表的时候把表名用双引号括起来试试看事实上你给出的错误信息里也可以证实这一点,你有没有发现drop table if exists user这一句报错信息里drop if exists user都是红色的?这说明了它们都是关键字。补充:(stackOverFlow的回答)[https://stackoverflow.com/questions/70797504/spring-data-jpa-h2-database-is-returning-ddl-error-during-table-creation]这篇回答是和你一样的情况:基本上提出了几种可能:1.你的pom.xml中引入的h2数据库版本不对,没有成功引入h22.如果不是1,解决方法比较通用的是使用

@Table(name = "\"user\"")

或者

@Table(name = "`user`")

加在实体类上面3、似乎从h2的v2.1.x版本后user作为关键字被确定了下来之前的版本则没有这个问题4、有人已经把这个问题作为issues提交给了hibernate官方:(https://hibernate.atlassian.net/browse/HHH-15079)官方的建议是暂时参阅:(https://docs.jboss.org/hibernate/stable/orm/userguide/html_si...)的第26.6.3节:即设置:

hibernate.globally_quoted_identifiers=true

这样做默认给所有的表名都加上引号来规避关键字的情况有一个老哥表示这样写也会给正常的表名加上引号,并可能引入更多错误,他推荐这样配置:

spring.jpa.properties.hibernate.auto_quote_keyword=true

5、你贴出的文章例子里的实体类上标明了@Table(name="user"),你的似乎没有,考虑一下加上,如果不行请采用上面的转义写法6、你没有贴出你的配置和pom.xml文件,我不清楚你的情况是属于哪一种,但是这个问题应该是可以通过上面的措施解决的

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容