@UniqueConstraint und @Column (unique = true) in Annotation im Ruhezustand

104

Was ist der Unterschied zwischen @UniqueConstraint und @Column (unique = true) ?

Beispielsweise:

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

Und

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

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;
navid_gh
quelle
2
Hinweis: Bei Hibernate 5.4 wurde unique=trueder Index beim Hinzufügen nicht vom automatischen Schema-Updater hinzugefügt. @UniqueConstraintließ es erscheinen. Könnte ein Fehler sein.
Ondra Žižka

Antworten:

147

Wie bereits erwähnt, @Column(unique = true)handelt es sich um eine Verknüpfung, UniqueConstraintwenn es sich nur um ein einzelnes Feld handelt.

Aus dem Beispiel, das Sie gegeben haben, gibt es einen großen Unterschied zwischen beiden.

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

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

Dieser Code impliziert, dass beide maskund groupeindeutig sein müssen, jedoch getrennt. Das heißt, wenn Sie beispielsweise einen Datensatz mit einer mask.id = 1 haben und versuchen, einen anderen Datensatz mit mask.id = 1 einzufügen , wird eine Fehlermeldung angezeigt , da diese Spalte eindeutige Werte haben sollte. Das gleiche gilt für die Gruppe.

Andererseits,

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

Impliziert, dass die Werte von mask + group kombiniert eindeutig sein sollten. Das heißt, Sie können beispielsweise einen Datensatz mit mask.id = 1 und group.id = 1 haben. Wenn Sie versuchen, einen anderen Datensatz mit mask.id = 1 und group.id = 2 einzufügen , wird dieser eingefügt erfolgreich, während es im ersten Fall nicht wäre.

Wenn Sie möchten, dass sowohl Maske als auch Gruppe separat und auf Klassenebene eindeutig sind, müssen Sie den Code wie folgt schreiben:

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

Dies hat den gleichen Effekt wie der erste Codeblock.

Glauber Néspoli
quelle
Kann ich nach dem Erstellen der eindeutigen Einschränkung die Einschränkung nach Namen in meinem JPA-Repository referenzieren, um sie abzufragen?
jDub9
@ jDub9 Sie können keinen Index abfragen. Sie können die Masken- und Gruppenspalten in einer Abfrage abfragen und diesen Index für eine schnellere Verarbeitung verwenden (wenn Sie Glück haben), aber Sie können nicht einfach einen Index abfragen.
Dalibor Filus
Beachten Sie jedoch, dass columnNames tatsächliche Namen in der Datenbank sein müssen. Dies sollte der Fall sein mask_idund group_idwenn Sie die Standardbenennungsstrategie verwenden.
vitro
27

Aus der Java EE-Dokumentation:

public abstract boolean unique

(Optional) Gibt an, ob die Eigenschaft ein eindeutiger Schlüssel ist. Dies ist eine Verknüpfung für die UniqueConstraint-Annotation auf Tabellenebene und nützlich, wenn die eindeutige Schlüsselbeschränkung nur ein einzelnes Feld ist. Diese Einschränkung gilt zusätzlich zu allen Einschränkungen, die durch die Primärschlüsselzuordnung entstehen, und für Einschränkungen, die auf Tabellenebene angegeben werden.

Siehe doc

Boas
quelle
Also, wenn ich diesen Code verwende: @Column (unique = true) @ManyToOne (optional = false, fetch = FetchType.EAGER) private ProductSerialMask-Maske; @Column (unique = true) @ManyToOne (optional = false, fetch = FetchType.EAGER) private Gruppengruppe; Ich habe zwei Indizes, aber wenn ich sie anders verwende, habe ich einen Index, der aus zwei Spalten besteht.
navid_gh
22

Neben Boaz 'Antwort ....

@UniqueConstraintMit dieser Option können Sie die Einschränkung benennen und gleichzeitig @Column(unique = true)einen zufälligen Namen generieren (z UK_3u5h7y36qqa13y3mauc5xxayq. B. ).

Manchmal kann es hilfreich sein zu wissen, welcher Tabelle eine Einschränkung zugeordnet ist. Z.B:

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

Zusätzlich zu den Antworten von @ Boaz und @ vegemite4me ....

Durch die Implementierung können ImplicitNamingStrategySie Regeln für die automatische Benennung der Einschränkungen erstellen. Beachten Sie, dass Sie Ihre Namensstrategie metadataBuilderwährend der Initialisierung von Hibernate hinzufügen :

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

Es funktioniert für @UniqueConstraint, aber nicht für @Column(unique = true), was immer einen zufälligen Namen generiert (z. B. UK_3u5h7y36qqa13y3mauc5xxayq).

Es gibt einen Fehlerbericht, um dieses Problem zu beheben. Wenn Sie können, stimmen Sie dort ab, um dies zu implementieren. Hier: https://hibernate.atlassian.net/browse/HHH-11586

Vielen Dank.

MarcG
quelle