非pk自动UUID(由Postgres在INSERT上生成)在匹配实体的JPA Repository.save()中失败



我有一个预先存在的Postgres表,用于自动生成非主键的UUID类型列的默认值。

DDL:

CREATE SEQUENCE IF NOT EXISTS uuid_column_table_seq;
CREATE TABLE IF NOT EXISTS uuid_column_table
(
uuid_column_table_id     integer  DEFAULT nextval('uuid_column_table_seq') NOT NULL,
not_pk_uuid              uuid     DEFAULT uuid_generate_v4()               NOT NULL,
label                    text,
PRIMARY KEY (uuid_column_table_id)
);

我有一个JPA实体(我正在尝试)匹配:

@Entity
@Table(name = "uuid_column_table")
public class UuidColumnTableEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer uuidColumnTableId;
@Column
@GeneratedValue
private UUID notPkUuid;
@Column
private String label;
public Integer getUuidColumnTableId() {
return this.uuidColumnTableId;
}
public void setUuidColumnTableId(Integer uuidColumnTableId) {
this.uuidColumnTableId = uuidColumnTableId;
}
public UUID getNotPkUuid() {
return this.notPkUuid;
}
public void setNotPkUuid(UUID notPkUuid) {
this.notPkUuid = notPkUuid;
}
public String getLabel() {
return this.label;
}
public void setLabel(String label) {
this.label = label;
}
}

当我执行以下代码时…

var uuidColumnTableEntity = new UuidColumnTableEntity();
uuidColumnTableEntity.setLabel("Test Label");
var uuidColumnTableEntityWithPk = UuidColumnTableEntityRepository.save(uuidColumnTableEntity);

…在UuidColumnTableEntityRepository.save()的JPA存储库上,我得到一个JPA异常:

could not execute statement; SQL [n/a]; constraint [not_pk_uuid" of relation "uuid_column_table]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

如果我无法更改Postgres DDL定义,我需要在定义JPA实体时纠正什么?

版本:

  • Java 17
  • Spring Boot 2.5.6
  • Jakarta Persistence 2.2.3
  • Postgres 13.3

注意:我搜索了一段时间,希望有人有一个附近的答案。然而,我发现许多问题和答案都是过时的。而那些更接近的时间是关于如何让JPA生成的值,而不是读回由PostgresINSERT生成的值。

您可以使用Hibernate的@Generated注释,这表明您正在注释的列是在数据库端生成的,并且需要在使用随后的select语句插入新记录之后检索。

JPA的@GeneratedValue注释用于定义主键生成,正如其他人指出的那样,不应该在这里使用。

感谢@Marco Belladielli的回答,我终于走上了解决这个问题的正确轨道。

tl;博士:特别…

  • 使用注释…
    • @GeneratedValue-带参数或不带参数,因为它只用于PK(主键)生成
    • @NotNull-即使Postgres DDL显式显示NOT NULL
  • 使用注释…
    • @Generated(...)-具有特别精确的参数
    • @Column(...)-同样,具有特别精确的参数

细节:

唯一的代码更改是实体的batchUuid属性。这是最终的工作:

import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
...
@Column(insertable = false, updatable = false, nullable = false)
@Generated(GenerationTime.INSERT)
private UUID notPkUuid;

相关内容