3.1 Afhankelijke entiteiten in kaart brengen

In SQL kunt u query's schrijven met behulp van JOIN. Is het mogelijk om hetzelfde te doen in HQL? Het korte antwoord is ja. Maar het volledige antwoord zal interessanter zijn.

Ten eerste, wanneer we een JOIN in SQL schrijven, betekent dit meestal dat de ene tabel verwijst naar een andere tabel. De takentabel bevat bijvoorbeeld een kolom employee_id die verwijst naar de kolom id van de werknemerstabel.

Deze afhankelijkheid kan worden beschreven met behulp van annotaties in Hibernate. Laten we eerst Entiteiten voor onze tabellen maken. Laten we eerst de werknemerstabel beschrijven:

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

En de klasse EmployeeTask voor de taaktabel :

@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 is in orde, maar er is één suggestie. Laten we eens kijken naar het veld employeeId in het laatste voorbeeld:

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

Merk je iets vreemds op? Zo niet, dan betekent dit dat je al een manier van denken in de SQL-taal hebt gevormd.

Het punt is dat we in de Java-taal zo'n afhankelijkheid meestal een beetje anders beschrijven:

public Employee employee;

We hoeven geen id op te geven , meestal specificeren we gewoon een variabele die een verwijzing naar het Employee- object bevat . Of slaat null op als er geen dergelijk object is.

En met Hibernate kunnen we zo'n situatie beschrijven met behulp van annotaties:

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

De annotatie @ManyToOnevertelt Hibernate dat veel EmployeeTask- entiteiten naar één Employee- entiteit kunnen verwijzen .

En de annotatie @JoinColumnspecificeert de naam van de kolom waaruit de id zal worden gehaald . Alle andere noodzakelijke informatie wordt gehaald uit de annotaties van de klasse Werknemer.

Het uiteindelijke resultaat ziet er als volgt uit:

@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 gebruiken in HQL

En laten we nu eens kijken hoe we query's kunnen schrijven naar gerelateerde entiteiten in HQL.

Eerste situatie.

We hebben een werknemer (Employee) en we willen een lijst met zijn taken. Dit is hoe die query eruit zou zien in SQL:

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

En laten we nu dezelfde query in HQL schrijven:

from EmployeeTask where employee.name = "Ivan Ivanovich"

De klasse EmployeeTask heeft een veld werknemer en een naamveld , dus deze query werkt.

Situatie twee.

Retourneer een lijst met werknemers die achterstallige taken hebben. Dit is hoe die query eruit zou zien in SQL:

SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();

DISTINCTwordt gebruikt omdat er veel taken aan één gebruiker kunnen worden toegewezen.

En laten we nu dezelfde query in HQL schrijven:

select distinct employee from EmployeeTask where deadline < CURDATE();

werknemer in deze query is een veld van de klasse EmployeeTask

Situatie drie.

Wijs alle niet-toegewezen taken toe aan de directeur. De SQL-query ziet er als volgt uit:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

En laten we nu dezelfde query in HQL schrijven:

update EmployeeTask set employee = :user where employee is null

De laatste vraag is de moeilijkste. We moeten de ID doorgeven, directeur, maar de klasse EmployeeTask bevat geen veld waarin u id kunt schrijven, maar bevat een veld Werknemer waarin u een verwijzing moet toewijzen aan een object van het type Werknemer.

In Hibernate wordt dit probleem opgelost met behulp van queryparameters die worden doorgegeven aan het Query-object. En in HQL zelf worden dergelijke parameters geschreven via een dubbele punt: :user. Maar we zullen hier later over praten.