我有一个预先存在的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;