@UniqueConstraint та @Column (унікальний = вірний) у сплячій анотації


104

У чому різниця між @UniqueConstraint і @Column (унікальний = істина) ?

Наприклад:

@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žka

Відповіді:


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

@ jDub9 Ви не можете запитувати індекс. Ви можете запитувати стовпці масок та груп у одному запиті, і він буде використовувати цей індекс для швидшої обробки (якщо вам пощастить), але ви не можете просто запитати індекс.
Далібор Філус

Остерігайтеся, хоча ці імена стовпців повинні бути фактичними іменами в базі даних. Це має бути mask_idі group_idякщо ви використовуєте стратегію іменування за замовчуванням.
vitro

27

З документації Java EE:

public abstract boolean unique

(Необов’язково) чи унікальний ключ властивості. Це ярлик для анотації UniqueConstraint на рівні таблиці і корисний, коли унікальне обмеження ключа є лише одним полем. Це обмеження застосовується на додаток до будь-якого обмеження, пов’язаного з відображенням первинного ключа, та обмежень, визначених на рівні таблиці.

Див. Док


тому, коли я використовую цей код: @Column (унікальний = true) @ManyToOne (необов’язково = false, fetch = FetchType.EAGER) приватна маска ProductSerialMask; @Column (унікальний = true) @ManyToOne (необов'язково = false, fetch = FetchType.EAGER) приватна група групи; У мене є два індекси, але при використанні іншим способом у мене є один індекс, що він поєднується з двох стовпців?
navid_gh

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ви можете створити правила для автоматичного іменування обмежень. Зауважте, що ви додаєте стратегію іменування metadataBuilderпід час ініціалізації в режимі Hibernate:

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

Він працює для @UniqueConstraint, але не для @Column(unique = true), який завжди генерує випадкове ім'я (наприклад, UK_3u5h7y36qqa13y3mauc5xxayq).

Існує звіт про помилки, щоб вирішити цю проблему, тому, якщо можете, будь ласка, проголосуйте там, щоб це було реалізовано. Тут: https://hibernate.atlassian.net/browse/HHH-11586

Дякую.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.