3.1 Cartografierea entităților dependente

În SQL, puteți scrie interogări folosind JOIN. Este posibil să faci același lucru în HQL? Răspunsul scurt este da. Dar răspunsul complet va fi mai interesant.

În primul rând, când scriem un JOIN în SQL, cel mai adesea înseamnă că un tabel se referă la un alt tabel. De exemplu, tabelul de activități conține o coloană employee_id care se referă la coloana id a tabelului angajat.

Această dependență poate fi descrisă folosind adnotări în Hibernate. Mai întâi, să creăm Entități pentru tabelele noastre. Mai întâi, să descriem tabelul angajaților:

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

Și clasa EmployeeTask pentru tabelul de sarcini :

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

Totul este bine, dar există o sugestie. Să ne uităm la câmpul employeeId din ultimul exemplu:

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

Observați ceva ciudat? Dacă nu, înseamnă că v-ați format deja un mod de a gândi în limbajul SQL.

Chestia este că, în limbajul Java, de obicei descriem o astfel de dependență puțin diferit:

public Employee employee;

Nu trebuie să specificăm un id , de obicei specificăm doar o variabilă care conține o referință la obiectul Employee . Sau stochează null dacă nu există un astfel de obiect.

Și Hibernate ne permite să descriem o astfel de situație folosind adnotări:

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

Adnotarea @ManyToOneîi spune lui Hibernate că multe entități EmployeeTask se pot referi la o entitate Employee .

Iar adnotarea @JoinColumnspecifică numele coloanei din care va fi luat id-ul . Toate celelalte informații necesare vor fi preluate din adnotările clasei Angajat.

Rezultatul final va arăta astfel:

@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 Utilizarea join în HQL

Și acum să ne uităm la cum să scrieți interogări către entitățile asociate în HQL.

Prima situație.

Avem un angajat (Angajat) și vrem să obținem o listă cu sarcinile sale. Iată cum ar arăta acea interogare în SQL:

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

Și acum să scriem aceeași interogare în HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Clasa EmployeeTask are un câmp de angajat și are un câmp de nume , astfel încât această interogare va funcționa.

Situatia a doua.

Returnați o listă cu angajații care au sarcini restante. Iată cum ar arăta acea interogare în SQL:

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

DISTINCTeste utilizat deoarece pot fi multe sarcini atribuite unui singur utilizator.

Și acum să scriem aceeași interogare în HQL:

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

angajat din această interogare este un câmp al clasei EmployeeTask

Situația trei.

Atribuiți directorului toate sarcinile nealocate. Interogarea SQL va arăta astfel:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Și acum să scriem aceeași interogare în HQL:

update EmployeeTask set employee = :user where employee is null

Ultima interogare este cea mai grea. Trebuie să transmitem ID-ul, director, dar clasa EmployeeTask nu conține un câmp în care puteți scrie id, în schimb conține un câmp Employee unde trebuie să atribuiți o referință unui obiect de tip Employee.

În Hibernate, această problemă este rezolvată cu ajutorul parametrilor de interogare care sunt trecuți obiectului Query. Și în HQL în sine, astfel de parametri sunt scriși prin două puncte: :user. Dar despre asta vom vorbi puțin mai târziu.