Como introduzir a restrição de várias colunas com anotações JPA?

90

Estou tentando introduzir uma restrição de várias chaves em uma entidade mapeada por JPA:

public class InventoryItem {
    @Id
    private Long id;

    @Version 
    private Long version;

    @ManyToOne
    @JoinColumn("productId")
    private Product product;

    @Column(nullable=false);
    private long serial;
}

Basicamente, o par (produto, serial) deve ser único, mas só encontrei uma maneira de dizer que o serial deve ser único. Obviamente, isso não é uma boa ideia, pois produtos diferentes podem ter os mesmos números de série.

Existe uma maneira de gerar essa restrição via JPA ou sou forçado a criá-la manualmente para o banco de dados?

plouh
fonte

Respostas:

185

Você pode declarar restrições exclusivas usando a @Table(uniqueConstraints = ...)anotação em sua classe de entidade, ou seja,

@Entity
@Table(uniqueConstraints={
    @UniqueConstraint(columnNames = {"productId", "serial"})
}) 
public class InventoryItem {
    ...
}

Observe que isso não cria magicamente a restrição exclusiva no banco de dados, você ainda precisa de um DDL para que ele seja criado. Mas parece que você está usando algum tipo de ferramenta automatizada para criar o banco de dados com base nas definições de entidade JPA.

psp
fonte
1
Esse tipo de coisa é necessário para um banco de dados existente com restrições já implementadas?
Rob
Eu acredito que a restrição será criada, o provedor JPA está criando o banco de dados.
AlanObject de
A exclusividade é para coluna (productId) e coluna (serial) ou para restrição de 2 colunas no total (productId, serial)?
P Satish Patro de
68

Como já respondido, o índice de várias colunas pode ser adicionado usando @Tableanotação. No entanto, columnNamesprecisa ser o nome das colunas reais do banco de dados, não o atributo de classe. Portanto, se a coluna for assim:

@Column(name="product_id")
Long productId;

Então a @Tableanotação deve ser como a seguinte

@Table(uniqueConstraints=
       @UniqueConstraint(columnNames = {"product_id", "serial"}) 
SJha
fonte
9
Este é um esclarecimento muito importante: nomes de tabelas e não nomes de objetos.
Calabacin
1
A exclusividade é para coluna (productId) e coluna (serial) ou para restrição de 2 colunas no total (productId, serial)?
P Satish Patro de
Kotlin: dê uma olhada nesta resposta para encontrar um exemplo de kotlin: stackoverflow.com/a/47000044/285431
Dirk
Erro de sintaxe. Você está faltando o parêntese de fechamento na anotação @Table.
Evvo