3.1 Abhängige Entitäten zuordnen

In SQL können Sie Abfragen mit JOIN schreiben. Ist das auch in HQL möglich? Die kurze Antwort lautet: Ja. Aber die vollständige Antwort wird interessanter sein.

Erstens bedeutet das Schreiben eines JOIN in SQL meist, dass eine Tabelle auf eine andere Tabelle verweist. Beispielsweise enthält die Aufgabentabelle eine Spalte „employee_id“, die auf die Spalte „id“ der Tabelle „employee“ verweist.

Diese Abhängigkeit kann mithilfe von Anmerkungen in Hibernate beschrieben werden. Erstellen wir zunächst einfach Entitäten für unsere Tabellen. Beschreiben wir zunächst die Mitarbeitertabelle:

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

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

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

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

Und die EmployeeTask- Klasse für die Aufgabentabelle :

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

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

   @Column(name="employee_id")
   public Integer employeeId;

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

Alles ist in Ordnung, aber es gibt einen Vorschlag. Schauen wir uns das Feld „employeeId“ im letzten Beispiel an:

@Column(name="employee_id")
public Integer employeeId;

Fällt Ihnen etwas Seltsames auf? Wenn nicht, bedeutet dies, dass Sie bereits eine Denkweise in der SQL-Sprache entwickelt haben.

Die Sache ist, dass wir in der Java-Sprache eine solche Abhängigkeit normalerweise etwas anders beschreiben:

public Employee employee;

Wir müssen keine ID angeben , sondern geben normalerweise nur eine Variable an, die einen Verweis auf das Employee- Objekt enthält . Oder speichert null, wenn kein solches Objekt vorhanden ist.

Und Hibernate ermöglicht es uns, eine solche Situation mithilfe von Anmerkungen zu beschreiben:

@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;

Die Annotation @ManyToOneteilt Hibernate mit, dass viele EmployeeTask- Entitäten auf eine Employee- Entität verweisen können .

Und die Anmerkung @JoinColumngibt den Namen der Spalte an, aus der die ID entnommen wird . Alle weiteren notwendigen Informationen werden den Annotationen der Employee-Klasse entnommen.

Das Endergebnis wird so aussehen:

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

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

   @ManyToOne
   @JoinColumn(name="employee_id", nullable=true)
   public Employee employee;

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

3.2 Join in HQL verwenden

Schauen wir uns nun an, wie man Abfragen an verwandte Entitäten in HQL schreibt.

Erste Situation.

Wir haben einen Mitarbeiter (Mitarbeiter) und möchten eine Liste seiner Aufgaben erhalten. So würde diese Abfrage in SQL aussehen:

SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";

Und jetzt schreiben wir dieselbe Abfrage in HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Die EmployeeTask- Klasse verfügt über ein Mitarbeiterfeld und ein Namensfeld , sodass diese Abfrage funktioniert.

Situation zwei.

Geben Sie eine Liste der Mitarbeiter zurück, die überfällige Aufgaben haben. 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();

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

„Mitarbeiter“ in dieser Abfrage ist ein Feld der Klasse „EmployeeTask“ .

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 „director“ übergeben, aber die Klasse „EmployeeTask“ enthält kein Feld, in das Sie „id“ schreiben können, sondern ein Feld „Employee“, in das Sie einem Objekt vom Typ „Employee“ eine Referenz zuweisen müssen.

In Hibernate wird dieses Problem mit Hilfe von Abfrageparametern gelöst, die an das Query-Objekt übergeben werden. Und in HQL selbst werden solche Parameter durch einen Doppelpunkt geschrieben: :user. Aber darüber werden wir etwas später sprechen.