Clés primaires composites dans JPA

1. Introduction

Dans ce didacticiel, nous découvrirons les clés primaires composites et les annotations correspondantes dans JPA.

2. Clés primaires composites

Une clé primaire composite - également appelée clé composite - est une combinaison de deux colonnes ou plus pour former une clé primaire pour une table.

Dans JPA, nous avons deux options pour définir les clés composites: Les annotations @IdClass et @EmbeddedId .

Afin de définir les clés primaires composites, nous devons suivre certaines règles:

  • La classe de clé primaire composite doit être publique
  • Il doit avoir un constructeur sans argument
  • Il doit définir les méthodes equals () et hashCode ()
  • Il doit être S erializable

3. L' annotation IdClass

Disons que nous avons une table appelée Account et qu'elle comporte deux colonnes - accountNumber, accountType - qui forment la clé composite. Nous devons maintenant le mapper dans JPA.

Conformément à la spécification JPA, créons une classe AccountId avec ces champs de clé primaire:

public class AccountId implements Serializable { private String accountNumber; private String accountType; // default constructor public AccountId(String accountNumber, String accountType) { this.accountNumber = accountNumber; this.accountType = accountType; } // equals() and hashCode() }

Ensuite, associons la classe AccountId à l'entité Account .

Pour ce faire, nous devons annoter l'entité avec l' annotation @IdClass . Nous devons également déclarer les champs de la classe AccountId dans l'entité Account et les annoter avec @Id :

@Entity @IdClass(AccountId.class) public class Account { @Id private String accountNumber; @Id private String accountType; // other fields, getters and setters }

4. L' annotation EmbeddedId

@EmbeddedId est une alternative à l' annotation @IdClass .

Prenons un autre exemple où nous devons conserver certaines informations d'un livre avec le titre et la langue comme champs de clé primaire.

Dans ce cas, la classe de clé primaire, BookId, doit être annotée avec @Embeddable :

@Embeddable public class BookId implements Serializable { private String title; private String language; // default constructor public BookId(String title, String language) { this.title = title; this.language = language; } // getters, equals() and hashCode() methods }

Ensuite, nous devons intégrer cette classe dans l' entité B ook en utilisant @EmbeddedId :

@Entity public class Book { @EmbeddedId private BookId bookId; // constructors, other fields, getters and setters }

5. @IdClass contre @EmbeddedId

Comme nous venons de le voir, la différence en surface entre ces deux est qu'avec @IdClass , nous avons dû spécifier les colonnes deux fois - une fois dans AccountId et à nouveau dans Account. Mais, avec @EmbeddedId, nous ne l'avons pas fait.

Il existe cependant d'autres compromis.

Par exemple, ces différentes structures affectent les requêtes JPQL que nous écrivons.

Par exemple, avec @IdClass , la requête est un peu plus simple:

SELECT account.accountNumber FROM Account account

Avec @EmbeddedId , nous devons faire un parcours supplémentaire:

SELECT book.bookId.title FROM Book book

De plus, @IdClass peut être très utile dans les endroits où nous utilisons une classe de clé composite que nous ne pouvons pas modifier.

Enfin, si nous voulons accéder individuellement à des parties de la clé composite, nous pouvons utiliser @IdClass, mais dans les endroits où nous utilisons fréquemment l'identifiant complet comme objet, @EmbeddedId est préféré.

6. Conclusion

Dans cet article rapide, nous explorons les clés primaires composites dans JPA.

Comme toujours, le code complet de cet article est disponible sur Github.