3.1 Cartographier les entités dépendantes

En SQL, vous pouvez écrire des requêtes en utilisant JOIN. Est-il possible de faire la même chose en HQL ? La reponse courte est oui. Mais la réponse complète sera plus intéressante.

Premièrement, lorsque nous écrivons un JOIN en SQL, cela signifie le plus souvent qu'une table fait référence à une autre table. Par exemple, la table des tâches contient une colonne employee_id qui fait référence à la colonne id de la table employee.

Cette dépendance peut être décrite à l'aide d'annotations dans Hibernate. Tout d'abord, créons simplement des entités pour nos tables. Commençons par décrire la table des employés :

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

Et la classe EmployeeTask pour la table des tâches :

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

Tout va bien, mais il y a une suggestion. Regardons le champ employeeId dans le dernier exemple :

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

Avez-vous remarqué quelque chose d'étrange? Si ce n'est pas le cas, cela signifie que vous avez déjà formé une façon de penser dans le langage SQL.

Le fait est que dans le langage Java, nous décrivons généralement une telle dépendance un peu différemment :

public Employee employee;

Nous n'avons pas besoin de spécifier un id , nous spécifions généralement simplement une variable qui contient une référence à l' objet Employee . Ou stocke null s'il n'y a pas un tel objet.

Et Hibernate nous permet de décrire une telle situation à l'aide d'annotations :

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

L'annotation @ManyToOneindique à Hibernate que de nombreuses entités EmployeeTask peuvent faire référence à une seule entité Employee .

Et l'annotation @JoinColumnprécise le nom de la colonne à partir de laquelle l'id sera extrait . Toutes les autres informations nécessaires seront tirées des annotations de la classe Employé.

Le résultat final ressemblera à ceci :

@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 Utiliser la jointure dans HQL

Et maintenant, regardons comment écrire des requêtes à des entités liées dans HQL.

Premier état des lieux.

Nous avons un employé (Employee) et nous voulons obtenir une liste de ses tâches. Voici à quoi ressemblerait cette requête en SQL :

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

Et maintenant, écrivons la même requête en HQL :

from EmployeeTask where employee.name = "Ivan Ivanovich"

La classe EmployeeTask a un champ employee et un champ name , donc cette requête fonctionnera.

Situation deux.

Renvoie une liste des employés qui ont des tâches en retard. Voici à quoi ressemblerait cette requête en SQL :

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

DISTINCTest utilisé car de nombreuses tâches peuvent être affectées à un seul utilisateur.

Et maintenant, écrivons la même requête en HQL :

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

employé dans cette requête est un champ de la classe EmployeeTask

Situation trois.

Attribuez toutes les tâches non assignées au directeur. La requête SQL ressemblera à ceci :

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Et maintenant, écrivons la même requête en HQL :

update EmployeeTask set employee = :user where employee is null

La dernière requête est la plus difficile. Nous devons passer l'ID, directeur, mais la classe EmployeeTask ne contient pas de champ où vous pouvez écrire id, mais contient un champ Employee où vous devez attribuer une référence à un objet de type Employee.

Dans Hibernate, ce problème est résolu à l'aide de paramètres de requête transmis à l'objet Query. Et dans HQL lui-même, ces paramètres sont écrits via deux-points : :user. Mais nous en reparlerons un peu plus tard.