3.1 Mappatura delle entità dipendenti

In SQL, puoi scrivere query usando JOIN. È possibile fare lo stesso in HQL? La risposta breve è sì. Ma la risposta completa sarà più interessante.

Innanzitutto, quando scriviamo un JOIN in SQL, molto spesso significa che una tabella fa riferimento a un'altra tabella. Ad esempio, la tabella delle attività contiene una colonna employee_id che fa riferimento alla colonna id della tabella employee.

Questa dipendenza può essere descritta utilizzando le annotazioni in Hibernate. Innanzitutto, creiamo entità per le nostre tabelle. Per prima cosa, descriviamo la tabella dei dipendenti:

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

E la classe EmployeeTask per la tabella delle attività :

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

Va tutto bene, ma c'è un suggerimento. Diamo un'occhiata al campo employeeId nell'ultimo esempio:

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

Notate qualcosa di strano? In caso contrario, significa che hai già formato un modo di pensare nel linguaggio SQL.

Il fatto è che nel linguaggio Java di solito descriviamo tale dipendenza in modo leggermente diverso:

public Employee employee;

Non abbiamo bisogno di specificare un id , di solito specifichiamo solo una variabile che contiene un riferimento all'oggetto Employee . O memorizza null se non esiste tale oggetto.

E Hibernate ci permette di descrivere una situazione del genere usando le annotazioni:

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

L'annotazione @ManyToOneindica a Hibernate che molte entità EmployeeTask possono fare riferimento a un'entità Employee .

E l'annotazione @JoinColumnspecifica il nome della colonna da cui verrà preso l'id . Tutte le altre informazioni necessarie verranno prese dalle annotazioni della classe Employee.

Il risultato finale sarà simile a questo:

@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 Utilizzo di join in HQL

E ora diamo un'occhiata a come scrivere query a entità correlate in HQL.

Prima situazione.

Abbiamo un dipendente (dipendente) e vogliamo ottenere un elenco delle sue attività. Ecco come sarebbe quella query in SQL:

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

E ora scriviamo la stessa query in HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

La classe EmployeeTask ha un campo employee e ha un campo name , quindi questa query funzionerà.

Situazione due.

Restituisce un elenco di dipendenti che hanno attività scadute. Ecco come sarebbe quella query in SQL:

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

DISTINCTviene utilizzato perché possono essere assegnate molte attività a un utente.

E ora scriviamo la stessa query in HQL:

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

dipendente in questa query è un campo della classe EmployeeTask

Situazione tre.

Assegna tutte le attività non assegnate al direttore. La query SQL sarà simile a questa:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

E ora scriviamo la stessa query in HQL:

update EmployeeTask set employee = :user where employee is null

L'ultima domanda è la più difficile. Dobbiamo passare l'ID, director, ma la classe EmployeeTask non contiene un campo dove puoi scrivere id, invece contiene un campo Employee dove devi assegnare un riferimento a un oggetto di tipo Employee.

In Hibernate, questo problema viene risolto con l'aiuto di parametri di query che vengono passati all'oggetto Query. E nello stesso HQL, tali parametri sono scritti attraverso i due punti: :user. Ma ne parleremo un po 'più tardi.