首页 > 解决方案 > Spring Boot Hibernate 使用序列或身份生成实体 ID 的问题

问题描述

我使用 sprint boot、jpa、hibernate 和 PostgreSQL 开发了 Rest API。我的目标是能够生成自动递增的 id,以便与代码一起使用并使用 D Beaver 等数据库工具,而无需编写任何额外的查询来获取下一个 ID 值等。

我创建了实体User。我尝试通过两种方式生成 id:

  1. GenerationType.IDENTITY

使用 GenerationType.IDENTITY 时,它成功地创建了带有名称的表、带有名称user的序列并为columnuser_id_seq添加了默认值。数据库中的所有内容都符合预期,并且与数据库工具配合得很好,但是当我尝试从我的 API 插入新行时会出现问题。尝试插入新行时休眠执行查询user.idnextval('user_id_seq'::regclass)

select currval('user_id_seq')

获取 id 值,我收到错误

org.postgresql.util.PSQLException: ERROR: invalid name syntax

因为周围的那些报价user。它应该执行

select currval('user_id_seq')

我相信这里的问题是因为我使用user了作为保留关键字的表名,但我想保持这种方式,因为这个命名与其他表模式匹配。

  1. GenerationType.SEQUENCE

如果我使用注释:

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
@SequenceGenerator(name="user_generator", sequenceName = "user_id_seq", allocationSize=1)

它创建表'user',序列'user_id_seq'但不添加user.id列默认值,所以我不能使用数据库工具插入新行而不指定id值。但是使用这一代类型我的 API 工作正常。

还值得一提的是,我spring.jpa.hibernate.ddl-auto=create-drop每次都使用并手动删除和重新创建模式,因此不会留下任何不必要的序列/表。

@Entity
@Table(name = "`user`")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // other properties...

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    // other getters and setters...
}

所以......有可能以某种方式连接这两种方式并创建一个可行的解决方案吗?我需要为列设置默认值,并且休眠也知道如何生成该 ID。

PS 我不想在运行应用程序时更改表/实体命名或执行 SQL 以更正表。我相信应该有更好的方法。

标签: postgresqlhibernatespring-bootspring-data-jpa

解决方案


经过数小时的调试后,我最终扩展了 PostgreSQL82Dialect 并覆盖了 getIdentitySelectString 函数以从表名中删除引号。


推荐阅读