我有一个具有唯一约束的列的表。我希望约束检查推迟到提交时间。
如果我像这样使用Postgres SQL创建它(省略了许多列):
CREATE TABLE instrument
(
id bigint NOT NULL,
name character varying(255) NOT NULL,
CONSTRAINT instrument_pkey PRIMARY KEY (id),
CONSTRAINT instrument_name_key UNIQUE (name)
DEFERRABLE INITIALLY DEFERRED
)
然后一切按预期进行。
如果我将其定义为这样休眠:
import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.annotations.ForeignKey;
@Entity
@Table(name="instrument")
public class Instrument implements Versionable, Serializable {
private static final long serialVersionUID = 1L;
public static final String NAME_PROPERTY = "name";
@Version
private int version;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
private Long id;
@Column(name="name", unique=true, nullable=false)
private String name;
public Instrument() {
// null constructor to make Hibernate happy
}
public Instrument(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public int hashCode() {
return Objects.hashCode(getName());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Instrument) {
Instrument other = (Instrument)obj;
return Objects.equal(getName(), other.getName());
}
return false;
}
@Override
public String toString() {
return "Instrument [id=" + id + ", name=" + name + "]";
}
}
使用
hibernate.hbm2ddl create
创建表时,不会为名称的唯一约束指定初始延迟选项(正如预期的那样,因为我不知道如何请求它)当我运行应用程序时,坏事情就会发生。
特别是允许用户在两个仪器之间交换名称。如果他试图在inst1和inst2之间交换名称,就会抛出一个异常:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "instrument_name_key"
Detail: Key (name)=(inst1) already exists.
所以问题是:是否有Hibernate注释可用于指定列上约束的
INITIALLY DEFERRED
属性?我不是在找工作。在安装/设置过程中,我有一个额外的步骤来应用约束。我所希望的是一种消除额外步骤的方法。
最佳答案
不幸的是,Hibernate不支持延迟约束。
https://hibernate.atlassian.net/browse/HHH-2248
您可以尝试使用entityManager.flush()方法,假设您有名称为inst1和inst2的仪器:
Instrument inst1 = entityManager.find(Instrument.class, 1);
// change name of first Instrument to some random one
inst1.setName("inst3");
entityManager.flush();
Instrument inst2 = entityManager.find(Instrument.class, 2);
inst2.setName("inst1");
entityManager.flush();
inst1.setName("inst2");
或者,可以从DB获取实体,从DB中删除它们,执行flush并持久化更新的实体。这样你就不用编第三个名字了。
不确定这些解决方案的性能效果,您必须自己弄清楚。
关于postgresql - 可以使用Hibernate注释定义INITIALLY DEFERRED约束吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47317706/