@Plusieurs à plusieurs

Disponible

Tableau des services

Examinons maintenant un autre cas courant - plusieurs à plusieurs. Imaginons que nous ayons une relation plusieurs à plusieurs entre les tâches et les employés :

  • Un employé dans la table des employés peut effectuer plusieurs tâches à partir de la table des tâches.
  • Une tâche du tableau des tâches peut être attribuée à plusieurs employés.

Cette relation entre entités est appelée plusieurs à plusieurs. Et pour l'implémenter au niveau SQL, nous avons besoin d'une table de service supplémentaire. Appelons-le, par exemple, employee_task.

La table employee_task ne contiendra que deux colonnes :

  • id_employé
  • id_tâche

Chaque fois que nous attribuons une tâche spécifique à un utilisateur spécifique, une nouvelle ligne sera ajoutée à ce tableau. Exemple:

id_employé id_tâche
1 1
1 2
2 3

Eh bien, la table des tâches devrait perdre sa colonne employee_id . Cela n'a de sens que si la tâche ne peut être attribuée qu'à un seul employé. Si la tâche peut être affectée à plusieurs employés, ces informations doivent être stockées dans la table de service employee_task .

Relation au niveau de la table

Voici à quoi ressembleront nos nouvelles tables :

identifiant nom profession salaire âge join_date
1 Ivanov Ivan Programmeur 100000 25 2012-06-30
2 Petrov Petr Programmeur 80000 23 2013-08-12
3 Ivanov Sergueï Testeur 40000 trente 2014-01-01
4 Rabinovitch Moisha Directeur 200000 35 2015-05-12
5 Kirienko Anastasia Responsable administratif 40000 25 2015-10-10
6 Vaska Chat 1000 3 2018-11-11

Table des employés ( non modifiée ) :

Ce tableau comporte les colonnes suivantes :

  • identifiant INT
  • nom VARCHAR
  • métier VARCHAR
  • salaire INT
  • âge INT
  • join_date DATE

Et voici à quoi ressemble la table des tâches , perdu la colonne employee_id (marquée en rouge):

identifiant id_employé nom date limite
1 1 Correction d'un bug sur le frontend 2022-06-01
2 2 Correction d'un bug sur le backend 2022-06-15
3 5 Acheter du café 2022-07-01
4 5 Acheter du café 2022-08-01
5 5 Acheter du café 2022-09-01
6 (NUL) Nettoyer le bureau (NUL)
7 4 Profite de la vie (NUL)
8 6 Profite de la vie (NUL)

Ce tableau n'a plus que 3 colonnes :

  • id - numéro de tâche unique (et lignes du tableau)
  • id_employé - (supprimé)
  • name - le nom et la description de la tâche
  • date limite - l'heure jusqu'à laquelle la tâche doit être terminée

Nous avons également la table de service employee_task , où les données employee_id ont migré de la table des tâches :

id_employé id_tâche
1 1
2 2
5 3
5 4
5 5
(NUL) 6
4 7
6 8

J'ai délibérément enregistré temporairement la colonne supprimée dans la table des tâches afin que vous puissiez voir que les données qu'elle contient ont été déplacées vers la table employee_task.

Un autre point important est la ligne rouge "(NULL) 6" dans la table employee_task. Je l'ai marqué en rouge car il ne sera pas dans la table employee_task .

Si la tâche 7 est affectée à l'utilisateur 4, il doit y avoir une ligne (4, 7) dans la table employee_task.

Si la tâche 6 n'est assignée à personne, il n'y aura simplement aucun enregistrement pour elle dans la table employee_task. Voici à quoi ressembleront les versions finales de ces tableaux :

tableau des tâches :

identifiant nom date limite
1 Correction d'un bug sur le frontend 2022-06-01
2 Correction d'un bug sur le backend 2022-06-15
3 Acheter du café 2022-07-01
4 Acheter du café 2022-08-01
5 Acheter du café 2022-09-01
6 Nettoyer le bureau (NUL)
7 Profite de la vie (NUL)
8 Profite de la vie (NUL)

table employee_task :

id_employé id_tâche
1 1
2 2
5 3
5 4
5 5
4 7
6 8

Communication au niveau de la classe Java

Mais avec la communication au niveau des classes Entity, nous avons un ordre complet. Commençons par la bonne nouvelle.

Tout d'abord, Hibernate a une annotation spéciale @ManyToMany qui vous permet de bien décrire le cas d'une relation de table plusieurs-à-plusieurs.

Deuxièmement, deux classes Entity nous suffisent encore. Nous n'avons pas besoin d'une classe pour la table de service.

Voici à quoi ressembleront nos cours. La classe Employé dans sa forme originale :

@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="occupation")
   public String occupation;

   @Column(name="salary")
   public Integer salary;

   @Column(name="join_date")
   public Date join;
}

Et la classe EmployeeTask dans sa forme originale :

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String description;

   @Column(name="deadline")
   public Date deadline;
}

Annotation @ManyToMany

J'omettrai les champs existants dans les exemples, mais j'en ajouterai de nouveaux. Voici à quoi ils ressembleront. Classe d'employés :

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
	       joinColumns=  @JoinColumn(name="employee_id", referencedColumnName="id"),
           inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();

}

Et la classe EmployeeTask :

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
       	joinColumns=  @JoinColumn(name="task_id", referencedColumnName="id"),
       	inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
   private Set<Employee> employees = new HashSet<Employee>();

}

Il paraît que tout est compliqué, mais en fait tout est simple.

Tout d'abord, il utilise l' annotation @JoinTable (à ne pas confondre avec @JoinColumn), qui décrit la table de service employee_task.

Deuxièmement, il décrit que la colonne task_id de la table employee_task fait référence à la colonne id de la table des tâches.

Troisièmement, il indique que la colonne employee_id de la table employee_task fait référence à la colonne id de la table employee.

En fait, à l'aide d'annotations, nous avons décrit quelles données sont contenues dans la table employee_task et comment Hibernate doit les interpréter.

Mais maintenant, nous pouvons très facilement ajouter (et supprimer) une tâche à n'importe quel employé. Et ajoutez également n'importe quel interprète à n'importe quelle tâche.

Demander des exemples

Écrivons quelques requêtes intéressantes pour mieux comprendre le fonctionnement de ces champs ManyToMany. Et ils fonctionnent exactement comme prévu.

Tout d'abord, notre ancien code fonctionnera sans changement, puisque le directeur avait auparavant un champ tâches :

EmployeeTask task1 = new EmployeeTask();
task1.description = "Do Something Important";
session.persist(task1);

EmployeeTask task2 = new EmployeeTask();
task2.description = "Nothing to do";
session.persist(task2);
session.flush();

Employee director = session.find(Employee.class, 4);
director.tasks.add(task1);
director.tasks.add(task2);

session.update(director);
session.flush();

Deuxièmement, si nous voulons affecter un autre interprète à une tâche, il est encore plus facile de le faire :

Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);

session.update(task);
session.flush();

Important! À la suite de l'exécution de cette demande, non seulement la tâche aura un exécuteur-directeur, mais également le directeur aura la tâche n ° 101.

Tout d'abord, le fait concernant la relation entre le directeur et la tâche dans la table employee_task sera stocké sous forme de chaîne : (4,101).

Deuxièmement, les champs marqués d'annotations @ManyToMany sont des objets proxy, et lorsqu'on y accède, une requête de base de données est toujours exécutée.

Ainsi, si vous ajoutez une tâche à un employé et enregistrez des informations sur l'employé dans la base de données, la tâche aura ensuite un nouvel exécuteur dans la liste des exécuteurs.

Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires