hibernateアノテーションの@UniqueConstraintおよび@Column(unique = true)


104

@UniqueConstraint@Column(unique = true)の違いは何ですか?

例えば:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {@UniqueConstraint(columnNames = {"mask", "group"})}
)

そして

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

2
注:Hibernate 5.4では、を追加したときにunique=true、スキームの自動アップデーターによってインデックスが追加されませんでした。@UniqueConstraintそれを出現させた。バグかもしれません。
OndraŽižka2017

回答:


147

前に述べたように、それが単一のフィールドのみの場合の@Column(unique = true)ショートカットUniqueConstraintです。

あなたが与えた例から、両方の間に大きな違いがあります。

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

このコードは、両方のことを意味maskし、group個別に一意である必要がありますが、。たとえば、あなたが持つレコードがある場合ことを意味しmask.id = 1で別のレコードを挿入すると、試行mask.id = 1をその列が一意の値を持っている必要があるので、あなたは、エラーを取得します。同じことがグループにも当てはまります。

一方、

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {@UniqueConstraint(columnNames = {"mask", "group"})}
)

マスク+グループの値の組み合わせが一意であることを意味します。つまり、たとえば、mask.id = 1およびgroup.id = 1のレコードを持つことができ、mask.id = 1およびgroup.id = 2の別のレコードを挿入しようとすると、そのレコードが挿入されます最初のケースでは成功しなかったのに対し、成功しました。

マスクとグループの両方を個別に、またクラスレベルで一意にしたい場合は、次のようにコードを記述する必要があります。

@Table(
        name = "product_serial_group_mask",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = "mask"),
                @UniqueConstraint(columnNames = "group")
        }
)

これは、最初のコードブロックと同じ効果があります。


一意の制約が作成されたら、JPAリポジトリで名前で制約を参照して、その制約を照会できますか?
jDub9 2018年

@ jDub9インデックスをクエリすることはできません。1つのクエリでマスク列とグループ列をクエリでき、そのインデックスを使用して処理が高速化されます(運が良ければ)が、単純にインデックスをクエリすることはできません。
Dalibor Filus

ただし、columnNamesはデータベース内の実際の名前でなければならないことに注意してください。デフォルトのネーミング戦略を使用する必要がmask_idありgroup_idます。
試験管

27

Java EEドキュメントから:

public abstract boolean unique

(オプション)プロパティが一意のキーかどうか。これはテーブルレベルでのUniqueConstraintアノテーションのショートカットであり、一意キー制約が単一のフィールドのみである場合に役立ちます。この制約は、主キーマッピングに伴う制約と、テーブルレベルで指定された制約に加えて適用されます。

ドキュメントを参照


したがって、このコードを使用すると、@ Column(unique = true)@ManyToOne(optional = false、fetch = FetchType.EAGER)private ProductSerialMask mask; @Column(unique = true)@ManyToOne(optional = false、fetch = FetchType.EAGER)プライベートグループグループ。2つのインデックスがありますが、他の方法を使用すると、2つの列を組み合わせた1つのインデックスがありますか?
navid_gh 2013年

22

ボアズの答えに加えて....

@UniqueConstraintランダムな名前(例:)を生成しながら、制約名前付けることができます。@Column(unique = true)UK_3u5h7y36qqa13y3mauc5xxayq

制約が関連付けられているテーブルを知ると役立つ場合があります。例えば:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {
      @UniqueConstraint(
          columnNames = {"mask", "group"},
          name="uk_product_serial_group_mask"
      )
   }
)

5

@Boazと@ vegemite4meの回答に加えて...

実装ImplicitNamingStrategyすることで、制約に自動的に名前を付けるルールを作成できます。metadataBuilderHibernateの初期化中に命名戦略をに追加することに注意してください。

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

これはに対して@UniqueConstraintは機能しますが、@Column(unique = true)常にランダムな名前を生成します(例:UK_3u5h7y36qqa13y3mauc5xxayq)。

この問題を解決するためのバグレポートがあるので、可能であれば、投票して実装してください。ここ:https : //hibernate.atlassian.net/browse/HHH-11586

ありがとう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.