Comment introduire une contrainte multi-colonnes avec des annotations JPA?

90

J'essaie d'introduire une contrainte multi-clé sur une entité mappée JPA:

public class InventoryItem {
    @Id
    private Long id;

    @Version 
    private Long version;

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

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

Fondamentalement, la paire (produit, série) doit être unique, mais j'ai seulement trouvé un moyen de dire que la série devrait être unique. Ce n'est évidemment pas une bonne idée car différents produits peuvent avoir les mêmes numéros de série.

Existe-t-il un moyen de générer cette contrainte via JPA ou suis-je obligé de la créer manuellement dans DB?

plouh
la source

Réponses:

185

Vous pouvez déclarer des contraintes uniques en utilisant l' @Table(uniqueConstraints = ...)annotation dans votre classe d'entité, c'est-à-dire

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

Notez que cela ne crée pas comme par magie la contrainte unique dans la base de données, vous avez toujours besoin d'un DDL pour qu'elle soit créée. Mais il semble que vous utilisiez une sorte d'outil automatisé pour créer la base de données basée sur les définitions d'entités JPA.

psp
la source
1
Est-ce que ce genre de chose est nécessaire pour une base de données existante avec des contraintes déjà en place?
Rob
Je pense que la contrainte sera créée, le fournisseur JPA crée la base de données.
AlanObject
L'unicité est pour la colonne (productId) et la colonne (serial) ou pour la contrainte de 2 colonnes au total (productId, serial)?
P Satish Patro
68

Comme déjà répondu, un index multi-colonnes peut être ajouté à l'aide d'une @Tableannotation. Cependant, columnNamesdoit être le nom des colonnes DB réelles, pas l'attribut de classe. Donc, si la colonne est comme la suivante:

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

Ensuite, l' @Tableannotation devrait ressembler à ce qui suit

@Table(uniqueConstraints=
       @UniqueConstraint(columnNames = {"product_id", "serial"}) 
SJha
la source
9
C'est une clarification très importante: les noms de table et non les noms d'objet.
Calabacin
1
L'unicité est pour la colonne (productId) et la colonne (serial) ou pour la contrainte de 2 colonnes au total (productId, serial)?
P Satish Patro
Kotlin: Jetez un œil sur cette réponse pour trouver un exemple pour kotlin: stackoverflow.com/a/47000044/285431
Dirk
Erreur de syntaxe. Il vous manque la parenthèse fermante sur l'annotation @Table.
Evvo du