2.1 Verlinkung auf Tabellenebene
Wir haben gesehen, wie Hibernate Sammlungen in Hilfstabellen speichert. Lassen Sie uns nun herausfinden, wie Sie Beziehungen zwischen vollwertigen Tabellen organisieren, in denen echte Entity-Klassen gespeichert sind.
Es gibt vier Arten von Beziehungen zwischen Entity-Klassen in Hibernate:
- eins zu eins
- eins -zu- viele
- viele zu eins
- viele zu viele
Und wir beginnen die Analyse mit der einfachsten Option – viele -zu- eins .
Sie sind bereits auf eine solche Beziehung zwischen Tabellen in SQL gestoßen. So sieht es normalerweise aus:
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:
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 Aufgaben für Mitarbeiter enthält:
Ausweis | Angestellten 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 nur 4 Spalten:
- id – eindeutige Aufgabennummer (und Zeilen in der Tabelle);
- Employee_id – Mitarbeiter-ID aus der Mitarbeitertabelle, der die Aufgabe zugewiesen ist;
- Name – Name und Beschreibung der Aufgabe;
- Frist – die Zeit, bis zu der die Aufgabe abgeschlossen sein muss.
Wir sehen, dass viele Zeilen in der Aufgabentabelle auf einen einzelnen Eintrag in der Mitarbeitertabelle verweisen können. Eine solche Beziehung auf Tabellenebene wird als Viele-zu- Eins-Beziehung bezeichnet.
2.2 Beziehung zur Java-Klassenebene
Neben der Kommunikation auf Tabellenebene können Sie in Hibernate auch die Kommunikation auf der Ebene von Entity-Klassen organisieren. Dies geschieht mit einer Annotation @ManyToOne
.
Aber zuerst erstellen wir einfach zwei Klassen: Employee und EmployeeTask :
@Entity
@Table(name="employee")
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 eine zweite Klasse zum Speichern von Mitarbeiterjobs:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@Column(name="employee_id")
public Integer employeeId;
@Column(name="deadline")
public Date deadline;
}
Mit diesen Klassen ist alles in Ordnung, aber es gibt keine Beziehung zwischen ihnen, die die Tatsache widerspiegeln würde, dass das Feld „employeeId“ der Klasse „EmployeeTask“ auf das Feld „id“ der Klasse „Employee“ verweist. Es ist Zeit, das Problem zu beheben
2.3 @ManyToOne-Annotation.
Erstens sind wir es in Java gewohnt, mit Objekten (und Objektreferenzen) und nicht mit deren ID zu operieren. Lassen Sie uns also zunächst anstelle des Felds „employeeId“ in der Klasse „EmployeeTask“ einfach auf ein Objekt vom Typ „Employee“ verweisen. So wird unsere neue Klasse aussehen:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@ManyToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
Mithilfe der Annotation @ManyToOne
haben wir darauf hingewiesen, dass viele EmployeeTask-Objekte auf ein Objekt vom Typ Employee verweisen können. Mithilfe der Annotation haben wir außerdem @JoinColumn
angegeben, in welcher Spalte unserer Tabelle die ID des Employee-Objekts gespeichert ist.
2.4 Beispiele anfordern
Lassen Sie uns nun einige Beispiele zeigen, wie Hibernate mit solchen verwandten Klassen arbeiten kann.
Szenario eins
Schreiben wir eine Abfrage, um alle Aufgaben herauszufinden, die einem bestimmten Benutzer zugewiesen wurden. So würde diese Abfrage in HQL aussehen:
from EmployeeTask where employee.name = "Ivan Ivanovich"
Sie können einfach durch einen Punkt auf Felder abhängiger Klassen verweisen. Es ist sehr bequem. Aber schreiben wir diese Abfrage trotzdem in Form von Java-Code:
String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
Szenario zwei
Schreiben wir eine Abfrage, die eine Liste der Mitarbeiter zurückgibt, die überfällige Aufgaben haben. Eine Aufgabe ist überfällig, wenn ihr Termin in der Vergangenheit liegt. So würde diese Abfrage in SQL aussehen:
SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();
DISTINCT
wird verwendet, da einem Benutzer viele Aufgaben zugewiesen werden können.
Und jetzt schreiben wir dieselbe Abfrage in HQL:
select distinct employee from EmployeeTask where deadline < CURDATE();
Employee ist in dieser Abfrage ein Feld der EmployeeTask-Klasse
Situation drei
Weisen Sie dem Direktor alle nicht zugewiesenen Aufgaben zu. Die SQL-Abfrage sieht folgendermaßen aus:
UPDATE task SET employee_id = 4 WHERE employee_id IS NULL
Und jetzt schreiben wir dieselbe Abfrage in HQL:
update EmployeeTask set employee = :user where employee is null
Die letzte Abfrage ist die schwierigste. Wir müssen die ID des Direktors übergeben, aber die EmployeeTask-Klasse enthält kein Feld, in das wir eine ID schreiben können, sondern ein Employee-Feld, in das wir einem Objekt vom Typ Employee eine Referenz zuweisen müssen.
Employee director = session.get(Employee.class, 4);
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();
GO TO FULL VERSION