2017-11-15 6 views
1

UNIQUE制約を持つ列を持つテーブルがあります。私は制約チェックがコミット時間を延期されるようにしたい。予想通りHibernateアノテーションを使用してINITIALLY DEFERRED制約を定義できますか?

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 
) 

その後、すべての作品:私は(多くの列が省略)このようにPostgresのSQLを使用して作成した場合

。私はこのようにHibernateにそれを定義した場合

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を使用し、INITIALLY DEFERREDオプションは、私は方法がわからないので、予想通り(名前のUNIQUE制約のために指定されていませんそれを求めるのです)。

私がアプリを実行すると、悪いことが起こります。

特に、ユーザーは2つの機器間で名前を入れ替えることができます。彼はINST1間とinst2の名前を交換しようとする場合には、例外がスローされます:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "instrument_name_key" 
    Detail: Key (name)=(inst1) already exists. 

そこで質問です:列の制約のINITIALLY DEFERREDプロパティを指定するために使用することができ、Hibernateの注釈がありますか?

PS:私は回避策を探していません。私は制約を適用するインストール/セットアッププロセスに特別なステップを持っています。私が望んでいるのは、その余分なステップを排除する方法です。

答えて

1

残念ながら、Hibernateは遅延制約をサポートしていません。 https://hibernate.atlassian.net/browse/HHH-2248

あなたは、あなたが名前INST1inst2ので楽器を持っているとしましょう、entityManager.flush()メソッドで遊んで試みることができる:

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から削除し、更新したエンティティをフラッシュして保持します。こうして、あなたは第3の名前を構成する必要はありません。

これらのソリューションのパフォーマンスの影響については、あなた自身を把握する必要があります。

関連する問題