Articles

Tutoriel d’annotation Hibernate One to Many

Introduction

Ce tutoriel d’Hibernation rapide nous présente un exemple de mappage un-à-plusieurs utilisant des annotations JPA, une alternative au XML.

Nous allons également apprendre ce que sont les relations bidirectionnelles, comment elles peuvent créer des incohérences et comment l’idée de propriété peut aider.

Pour en savoir plus:

Botte à ressort avec Hibernate

Une introduction rapide et pratique à l’intégration de la botte à ressort et de l’Hibernate /JPA.
En savoir plus →

Un aperçu des identifiants dans Hibernate/JPA

Apprenez à mapper les identifiants d’entité avec Hibernate.
Lire la suite →

Description

En termes simples, le mappage un-à-plusieurs signifie qu’une ligne d’une table est mappée à plusieurs lignes d’une autre table.

Regardons le diagramme de relation d’entité suivant pour voir une association un à plusieurs:

Pour cet exemple, nous allons implémenter un système de panier où nous avons une table pour chaque panier et une autre table pour chaque élément. Un panier peut contenir de nombreux articles, nous avons donc ici un mappage un à plusieurs.

La façon dont cela fonctionne au niveau de la base de données est que nous avons un cart_id comme clé primaire dans la table cart et également un cart_id comme clé étrangère dans les éléments.

La façon dont nous le faisons dans le code est avec @OneToMany.

Mappons la classe Cart à l’objet Items de manière à refléter la relation dans la base de données:

public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; //...}

Nous pouvons également ajouter une référence au Panier dans les éléments en utilisant @ManyToOne, ce qui en fait une relation bidirectionnelle. Bidirectionnel signifie que nous sommes en mesure d’accéder aux articles à partir de chariots, ainsi qu’aux chariots à partir d’articles.

La propriété mappedBy est ce que nous utilisons pour indiquer à Hibernate quelle variable nous utilisons pour représenter la classe parent dans notre classe enfant.

Les technologies et bibliothèques suivantes sont utilisées pour développer un exemple d’application Hibernate qui implémente une association un-à-plusieurs :

  • JDK 1.8 ou version ultérieure
  • Hibernate 5
  • Maven 3 ou version ultérieure
  • Base de données H2

Configuration

3.1. Configuration de la base de données

Voici notre script de base de données pour les tables de panier et d’articles. Nous utilisons la contrainte de clé étrangère pour le mappage un-à-plusieurs :

Notre configuration de base de données est prête, passons donc à la création de l’exemple de projet Hibernate.

3.2. Dépendances Maven

Nous ajouterons ensuite les dépendances de pilote Hibernate et H2 à notre pom.fichier xml. La dépendance Hibernate utilise la journalisation JBoss, et elle est automatiquement ajoutée en tant que dépendances transitives :

  • Hibernate version 5.2.7.Version finale du pilote H2 1.4.197

Veuillez visiter le référentiel central Maven pour les dernières versions d’Hibernate et des dépendances H2.

3.3. Configuration Hibernate

Voici la configuration de Hibernate :

3.4. Classe HibernateAnnotationUtil

Avec la classe HibernateAnnotationUtil, il suffit de référencer le nouveau fichier de configuration Hibernate :

Les modèles

Les configurations liées au mappage seront effectuées à l’aide d’annotations JPA dans les classes de modèles:

@Entity@Table(name="CART")public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; // getters and setters}

Veuillez noter que l’annotation @OneToMany est utilisée pour définir la propriété dans la classe Items qui sera utilisée pour mapper la variable mappedBy. C’est pourquoi nous avons une propriété nommée « cart” dans la classe Items :

Il est également important de noter que l’annotation @ManyToOne est associée à la variable de classe Cart. L’annotation @JoinColumn fait référence à la colonne mappée.

En action

Dans le programme de test, nous créons une classe avec une méthode main() pour obtenir la session d’Hibernation et enregistrer les objets du modèle dans la base de données implémentant l’association un à plusieurs:

C’est la sortie de notre programme de test:

L’Annotation @ManyToOne

Comme nous l’avons vu dans la section 2, nous pouvons spécifiez une relation plusieurs à un à l’aide de l’annotation @ManyToOne. Un mappage plusieurs vers un signifie que de nombreuses instances de cette entité sont mappées à une instance d’une autre entité – de nombreux éléments dans un panier.

L’annotation @ManyToOne nous permet également de créer des relations bidirectionnelles. Nous aborderons cela en détail dans les prochaines sous-sections.

6.1. Incohérences et propriété

Maintenant, si le panier référençait des articles, mais que les articles ne référencaient pas à leur tour le panier, notre relation serait unidirectionnelle. Les objets auraient également une consistance naturelle.

Dans notre cas cependant, la relation est bidirectionnelle, ce qui entraîne la possibilité d’incohérence.

Imaginons une situation où un développeur veut ajouter l’item1 au panier et l’item2 au cart2, mais commet une erreur de sorte que les références entre cart2 et l’item2 deviennent incohérentes:

Comme indiqué ci-dessus, l’item2 fait référence à cart2, alors que cart2 ne fait pas référence à l’item2, et c’est mauvais.

Comment Hibernate doit-il enregistrer l’item2 dans la base de données? La clé étrangère item2 fera-t-elle référence à cart1 ou cart2?

Nous résolvons cette ambiguïté en utilisant l’idée d’un côté propriétaire de la relation; les références appartenant au côté propriétaire ont priorité et sont enregistrées dans la base de données.

6.2. Éléments en tant que Côté propriétaire

Comme indiqué dans la spécification JPA sous la section 2.9, il est recommandé de marquer plusieurs côtés comme côté propriétaire.

En d’autres termes, les articles seraient le côté propriétaire et le panier le côté inverse, ce qui est exactement ce que nous avons fait plus tôt.

Alors, comment y sommes-nous parvenus?

En incluant l’attribut mappedBy dans la classe Cart, nous le marquons comme le côté inverse.

En même temps, nous annotons également les éléments.champ de panier avec @ManyToOne, faisant des articles le côté propriétaire.

Pour en revenir à notre exemple d' »incohérence”, Hibernate sait maintenant que la référence de l’item2 est plus importante et enregistrera la référence de l’item2 dans la base de données.

Vérifions le résultat:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=2

Bien que le panier fasse référence à l’item2 dans notre extrait de code, la référence d’item2 à cart2 est enregistrée dans la base de données.

6.3. Cart comme Côté propriétaire

Il est également possible de marquer le côté un à plusieurs comme côté propriétaire, et le côté plusieurs à un comme côté inverse.

Bien que ce ne soit pas une pratique recommandée, allons-y et essayons.

L’extrait de code ci-dessous montre l’implémentation du côté un à plusieurs en tant que côté propriétaire :

Remarquez comment nous avons supprimé l’élément mappedBy et défini le @JoinColumn plusieurs à un comme insérable et pouvant être mis à jour sur false.

Si nous exécutons le même code, le résultat sera le contraire:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=1

Comme indiqué ci-dessus, maintenant l’item2 appartient au panier.

Conclusion

Nous avons vu à quel point il est facile d’implémenter la relation un-à-plusieurs avec l’ORM Hibernate et la base de données H2 en utilisant des annotations JPA.

De plus, nous avons appris sur les relations bidirectionnelles et comment implémenter la notion de côté propriétaire.