@UniqueConstraint e @Column (unique = true) na anotação de hibernação


104

Qual é a diferença entre @UniqueConstraint e @Column (unique = true) ?

Por exemplo:

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

E

@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: Com o Hibernate 5.4, quando adicionei unique=true, o índice não foi adicionado pelo atualizador automático do esquema. @UniqueConstraintfez parecer. Pode ser um bug.
— Ondra Žižka

Respostas:


147

Como disse antes, @Column(unique = true)é um atalho paraUniqueConstraint quando é apenas um campo.

Pelo exemplo que você deu, há uma grande diferença entre os dois.

@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 maske groupdevem ser únicos, mas separadamente. Isso significa que se, por exemplo, você tiver um registro com mask.id = 1 e tentar inserir outro registro com mask.id = 1 , receberá um erro, porque essa coluna deve ter valores únicos. O mesmo se aplica ao grupo.

Por outro lado,

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

Implica que os valores de máscara + grupo combinados devem ser únicos. Isso significa que você pode ter, por exemplo, um registro com mask.id = 1 e group.id = 1 , e se você tentar inserir outro registro com mask.id = 1 e group.id = 2 , ele será inserido com sucesso, enquanto no primeiro caso não o faria.

Se você quiser que a máscara e o grupo sejam únicos separadamente e no nível da classe, você terá que escrever o código da seguinte forma:

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

Isso tem o mesmo efeito que o primeiro bloco de código.


Depois que a restrição exclusiva é criada, posso fazer referência à restrição por nome em meu Repositório JPA para consultá-la?
— jDub9

@ jDub9 Você não pode consultar um índice. Você pode consultar as colunas de máscara e grupo, em uma consulta, e ele usará esse índice para processamento mais rápido (se você tiver sorte), mas você não pode simplesmente consultar um índice.
— Dalibor Filus

Tenha cuidado, porém, que columnNames deve ser nomes reais no banco de dados. Deve ser mask_ide group_idse você usar a estratégia de nomenclatura padrão.
— vitro

27

Da documentação do Java EE:

public abstract boolean unique

(Opcional) Se a propriedade é uma chave exclusiva. Este é um atalho para a anotação UniqueConstraint no nível da tabela e é útil quando a restrição de chave exclusiva é apenas um único campo. Essa restrição se aplica além de qualquer restrição acarretada pelo mapeamento de chave primária e às restrições especificadas no nível da tabela.

Veja doc


então, quando eu uso este código: @Column (unique = true) @ManyToOne (optional = false, fetch = FetchType.EAGER) private ProductSerialMask mask; @Column (unique = true) @ManyToOne (opcional = false, fetch = FetchType.EAGER) Grupo privado do grupo; Tenho dois índices mas quando uso de outra forma tenho um índice que é combinação de duas colunas?
— navid_gh

22

Além da resposta de Boaz ....

@UniqueConstraintpermite nomear a restrição , enquanto @Column(unique = true)gera um nome aleatório (por exemplo UK_3u5h7y36qqa13y3mauc5xxayq).

Às vezes, pode ser útil saber a qual tabela uma restrição está associada. Por exemplo:

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

5

Além das respostas de @ Boaz e @ vegemite4me ....

Ao implementar, ImplicitNamingStrategyvocê pode criar regras para nomear automaticamente as restrições. Observe que você adiciona sua estratégia de nomenclatura ao metadataBuilderdurante a inicialização do Hibernate:

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

Ele funciona para @UniqueConstraint, mas não para @Column(unique = true), que sempre gera um nome aleatório (por exemplo, UK_3u5h7y36qqa13y3mauc5xxayq).

Há um relatório de bug para resolver esse problema, então se você puder, vote aqui para que isso seja implementado. Aqui: https://hibernate.atlassian.net/browse/HHH-11586

Obrigado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.