Servicetisch

Schauen wir uns nun einen weiteren häufigen Fall an – viele-zu-viele. Stellen wir uns vor, dass wir eine Viele-zu-Viele- Beziehung zwischen Aufgaben und Mitarbeitern haben :

  • Ein Mitarbeiter in der Mitarbeitertabelle kann viele Aufgaben aus der Aufgabentabelle erledigen.
  • Eine Aufgabe in der Aufgabentabelle kann mehreren Mitarbeitern zugewiesen werden.

Diese Beziehung zwischen Entitäten wird als Viele-zu-Viele bezeichnet. Und um es auf SQL-Ebene umzusetzen, benötigen wir eine zusätzliche Servicetabelle. Nennen wir es zum Beispiel „employee_task“.

Die Tabelle „employee_task“ enthält nur zwei Spalten:

  • Angestellten ID
  • task_id

Jedes Mal, wenn wir einem bestimmten Benutzer eine bestimmte Aufgabe zuweisen, wird dieser Tabelle eine neue Zeile hinzugefügt. Beispiel:

Angestellten ID task_id
1 1
1 2
2 3

Nun, die Aufgabentabelle sollte ihre Spalte „employee_id“ verlieren . Dies macht nur dann Sinn, wenn die Aufgabe nur einem Mitarbeiter zugewiesen werden kann. Wenn die Aufgabe mehreren Mitarbeitern zugewiesen werden kann, müssen diese Informationen in der Servicetabelle „employee_task“ gespeichert werden .

Beziehung auf Tabellenebene

So werden unsere neuen Tische aussehen:

Ausweis Name Beruf Gehalt Alter Beitrittsdatum
1 Iwanow Iwan Programmierer 100000 25 30.06.2012
2 Petrov Petr Programmierer 80000 23 12.08.2013
3 Iwanow Sergej Prüfer 40000 dreißig 01.01.2014
4 Rabinovich Moisha Direktor 200000 35 12.05.2015
5 Kirienko Anastasia Büroleiter 40000 25 10.10.2015
6 Vaska Der Kater 1000 3 11.11.2018

Mitarbeitertabelle ( nicht geändert ) :

Diese Tabelle hat die folgenden Spalten:

  • id INT
  • Namen VARCHAR
  • Beruf VARCHAR
  • Gehalt INT
  • Alter INT
  • join_date DATUM

Und so sieht die Aufgabentabelle aus , die Spalte „employee_id“ ist verloren gegangen (rot markiert):

Ausweis emploee_id Name Termin
1 1 Beheben Sie einen Fehler im Frontend 01.06.2022
2 2 Beheben Sie einen Fehler im Backend 15.06.2022
3 5 Kaffee kaufen 01.07.2022
4 5 Kaffee kaufen 01.08.2022
5 5 Kaffee kaufen 01.09.2022
6 (NULL) Räumen Sie das Büro auf (NULL)
7 4 Das Leben genießen (NULL)
8 6 Das Leben genießen (NULL)

Diese Tabelle hat jetzt nur noch 3 Spalten:

  • id – eindeutige Aufgabennummer (und Zeilen in der Tabelle)
  • Employee_id – (entfernt)
  • Name – der Name und die Beschreibung der Aufgabe
  • Frist – die Zeit, bis zu der die Aufgabe erledigt sein muss

Wir haben auch die Diensttabelle „employee_task“ , in die die Daten „employee_id“ aus der Aufgabentabelle migriert wurden:

Angestellten ID task_id
1 1
2 2
5 3
5 4
5 5
(NULL) 6
4 7
6 8

Ich habe die gelöschte Spalte absichtlich vorübergehend in der Aufgabentabelle gespeichert, damit Sie sehen können, dass die Daten daraus in die Tabelle „employee_task“ verschoben wurden.

Ein weiterer wichtiger Punkt ist die rote Linie „(NULL) 6“ in der Tabelle „employee_task“. Ich habe es rot markiert, da es nicht in der Tabelle „employee_task“ enthalten ist .

Wenn Aufgabe 7 dem Benutzer 4 zugewiesen ist, sollte es eine Zeile (4, 7) in der Tabelle „employee_task“ geben.

Wenn Aufgabe 6 niemandem zugewiesen ist, gibt es einfach keinen Eintrag dafür in der Tabelle „employee_task“. So werden die endgültigen Versionen dieser Tabellen aussehen:

Aufgabentabelle :

Ausweis Name Termin
1 Beheben Sie einen Fehler im Frontend 01.06.2022
2 Beheben Sie einen Fehler im Backend 15.06.2022
3 Kaffee kaufen 01.07.2022
4 Kaffee kaufen 01.08.2022
5 Kaffee kaufen 01.09.2022
6 Räumen Sie das Büro auf (NULL)
7 Das Leben genießen (NULL)
8 Das Leben genießen (NULL)

Employee_task-Tabelle:

Angestellten ID task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8

Kommunikation auf Java-Klassenebene

Aber mit der Kommunikation auf der Ebene der Entity-Klassen haben wir eine vollständige Ordnung. Beginnen wir mit den guten Nachrichten.

Erstens verfügt Hibernate über eine spezielle @ManyToMany- Annotation , mit der Sie den Fall einer Viele-zu-Viele-Tabellenbeziehung gut beschreiben können.

Zweitens reichen uns noch zwei Entity-Klassen. Wir brauchen keine Klasse für die Servicetabelle.

So werden unsere Kurse aussehen. Die Employee- Klasse in ihrer ursprünglichen Form:

@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;
}

Und die EmployeeTask- Klasse in ihrer ursprünglichen Form:

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

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

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

@ManyToMany-Anmerkung

Ich werde die vorhandenen Felder in den Beispielen weglassen, aber neue hinzufügen. So werden sie aussehen. Mitarbeiterklasse : _

@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>();

}

Und die EmployeeTask- Klasse :

@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>();

}

Es scheint, dass alles kompliziert ist, aber in Wirklichkeit ist alles einfach.

Erstens wird die Annotation @JoinTable (nicht zu verwechseln mit @JoinColumn) verwendet, die die Diensttabelle „employee_task“ beschreibt.

Zweitens wird beschrieben, dass sich die Spalte „task_id“ der Tabelle „employee_task“ auf die Spalte „id“ der Tabelle „task“ bezieht.

Drittens heißt es, dass sich die Spalte „employee_id“ der Tabelle „employee_task“ auf die Spalte „id“ der Tabelle „employee“ bezieht.

Tatsächlich haben wir mithilfe von Anmerkungen beschrieben, welche Daten in der Tabelle „employee_task“ enthalten sind und wie Hibernate diese interpretieren soll.

Aber jetzt können wir jedem Mitarbeiter ganz einfach eine Aufgabe hinzufügen (und löschen). Und fügen Sie auch beliebige Darsteller zu jeder Aufgabe hinzu.

Fordern Sie Beispiele an

Lassen Sie uns ein paar interessante Abfragen schreiben, um besser zu verstehen, wie diese ManyToMany-Felder funktionieren. Und sie funktionieren genau wie erwartet.

Erstens funktioniert unser alter Code ohne Änderungen, da der Direktor zuvor ein Aufgabenfeld hatte:

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();

Zweitens, wenn wir einer Aufgabe einen anderen Ausführenden zuweisen möchten, ist dies noch einfacher:

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

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

Wichtig! Durch die Ausführung dieser Anfrage erhält nicht nur die Aufgabe einen Testamentsvollstrecker-Direktor, sondern auch der Direktor erhält die Aufgabe Nr. 101.

Zunächst wird die Tatsache über die Beziehung zwischen dem Direktor und der Aufgabe in der Tabelle „employee_task“ als Zeichenfolge gespeichert: (4,101).

Zweitens sind die mit @ManyToMany- Annotationen gekennzeichneten Felder Proxy-Objekte, und wenn auf sie zugegriffen wird, wird immer eine Datenbankabfrage ausgeführt.

Wenn Sie also einem Mitarbeiter eine Aufgabe hinzufügen und Informationen über den Mitarbeiter in der Datenbank speichern, erhält die Aufgabe danach einen neuen Ausführenden in der Liste der Ausführenden.