web-dev-qa-db-ja.com

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

@ 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;
83
navid_gh

前に述べたように、@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;

このコードは、maskgroupの両方が一意である必要があることを意味しますが、別々にする必要があります。つまり、たとえば、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の別のレコードは、正常に挿入されますが、最初の場合はそうではありませんt。

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

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

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

124

Java EEドキュメントから:

public abstract boolean unique

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

doc を参照してください

27
Boaz

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

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

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

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

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

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

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

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

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

ありがとう。

5
MarcG