@UniqueConstraint y @Column (único = verdadero) en la anotación de hibernación


104

¿Cuál es la diferencia entre @UniqueConstraint y @Column (único = verdadero) ?

Por ejemplo:

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

Y

@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
Nota: Con Hibernate 5.4, cuando agregué unique=true, el actualizador automático de esquemas no agregó el índice. @UniqueConstraintlo hizo aparecer. Podría ser un error.
— Ondra Žižka

Respuestas:


147

Como se dijo antes, @Column(unique = true)es un atajo para UniqueConstraintcuando es un solo campo.

Por el ejemplo que dio, hay una gran diferencia entre ambos.

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

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

Este código implica que ambos masky grouptienen que ser únicos, pero por separado. Eso significa que si, por ejemplo, tiene un registro con mask.id = 1 e intenta insertar otro registro con mask.id = 1 , obtendrá un error, porque esa columna debe tener valores únicos. Lo mismo se aplica al grupo.

Por otra parte,

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

Implica que los valores de máscara + grupo combinados deben ser únicos. Eso significa que puede tener, por ejemplo, un registro con mask.id = 1 y group.id = 1 , y si intenta insertar otro registro con mask.id = 1 y group.id = 2 , se insertará con éxito, mientras que en el primer caso no lo haría.

Si desea que tanto la máscara como el grupo sean únicos por separado y para eso a nivel de clase, tendrá que escribir el código de la siguiente manera:

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

Esto tiene el mismo efecto que el primer bloque de código.


Una vez que se crea la restricción única, ¿puedo hacer referencia a la restricción por nombre en mi repositorio JPA para consultar sobre eso?
— jDub9

@ jDub9 No puede consultar un índice. Puede consultar la máscara y las columnas de grupo, en una consulta, y usará ese índice para un procesamiento más rápido (si tiene suerte), pero no puede simplemente consultar un índice.
— Dalibor Filus

Sin embargo, tenga en cuenta que columnNames debe ser nombres reales en la base de datos. Debería serlo mask_idy group_idsi usa la estrategia de nomenclatura predeterminada.
— vitro

27

De la documentación de Java EE:

public abstract boolean unique

(Opcional) Si la propiedad es una clave única. Este es un atajo para la anotación UniqueConstraint en el nivel de tabla y es útil cuando la restricción de clave única es solo un campo. Esta restricción se aplica además de cualquier restricción que conlleve la asignación de clave primaria y a las restricciones especificadas en el nivel de la tabla.

Ver documento


así que cuando uso este código: @Column (único = verdadero) @ManyToOne (opcional = falso, fetch = FetchType.EAGER) máscara de ProductSerialMask privada; @Column (único = verdadero) @ManyToOne (opcional = falso, fetch = FetchType.EAGER) grupo de grupo privado; Tengo dos índices, pero cuando lo uso de otra manera, ¿tengo un índice que es una combinación de dos columnas?
— navid_gh

22

Además de la respuesta de Booz ...

@UniqueConstraintle permite nombrar la restricción , mientras @Column(unique = true)genera un nombre aleatorio (por ejemplo UK_3u5h7y36qqa13y3mauc5xxayq).

A veces puede resultar útil saber con qué tabla está asociada una restricción. P.ej:

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

5

Además de las respuestas de @ Boaz y @ vegemite4me ...

Al implementarlo ImplicitNamingStrategy, puede crear reglas para nombrar automáticamente las restricciones. Tenga en cuenta que agrega su estrategia de nomenclatura metadataBuilderdurante la inicialización de Hibernate:

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

Funciona para @UniqueConstraint, pero no para @Column(unique = true), que siempre genera un nombre aleatorio (por ejemplo, UK_3u5h7y36qqa13y3mauc5xxayq).

Hay un informe de error para resolver este problema, así que si puede, vote allí para implementarlo. Aquí: https://hibernate.atlassian.net/browse/HHH-11586

Gracias.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.