3.1 Függő entitások leképezése

SQL-ben a JOIN használatával írhat lekérdezéseket. HQL-ben meg lehet csinálni ugyanezt? A rövid válasz: igen. De a teljes válasz érdekesebb lesz.

Először is, amikor SQL-ben írunk egy JOIN-t, az legtöbbször azt jelenti, hogy az egyik tábla egy másik táblára hivatkozik. Például a feladattábla tartalmaz egy alkalmazott_azonosító oszlopot, amely az alkalmazotti tábla id oszlopára hivatkozik.

Ez a függőség a hibernált állapot megjegyzéseivel írható le. Először is hozzunk létre entitásokat a tábláinkhoz. Először is írjuk le az alkalmazottak táblázatát:

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

És az EmployeeTask osztály a feladattáblázathoz :

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

Minden rendben van, de van egy javaslat. Nézzük meg az utolsó példa munkavállalóazonosító mezőjét:

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

Észrevesz valami furcsát? Ha nem, akkor ez azt jelenti, hogy már kialakított egy gondolkodásmódot az SQL nyelvben.

A helyzet az, hogy a Java nyelvben általában egy kicsit másképp írjuk le az ilyen függőséget:

public Employee employee;

Nem kell megadnunk az azonosítót , általában csak egy változót adunk meg , amely hivatkozást tartalmaz az Employee objektumra . Vagy nullát tárol , ha nincs ilyen objektum.

A Hibernate pedig lehetővé teszi egy ilyen helyzet leírását annotációk segítségével:

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

A megjegyzés @ManyToOneazt mondja a Hibernate-nak, hogy sok EmployeeTask entitás hivatkozhat egy Employee entitásra .

És a megjegyzés @JoinColumnmegadja annak az oszlopnak a nevét, amelyből az azonosítót veszik . Minden egyéb szükséges információt az Employee osztály megjegyzéseiből veszünk.

A végeredmény így fog kinézni:

@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 használata HQL-ben

És most nézzük meg, hogyan írhatunk lekérdezéseket a kapcsolódó entitásokhoz a HQL-ben.

Első szituáció.

Van egy alkalmazottunk (Employee), és szeretnénk listát kapni a feladatairól. Így nézne ki ez a lekérdezés SQL-ben:

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

És most írjuk be ugyanazt a lekérdezést HQL-ben:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Az EmployeeTask osztálynak van egy alkalmazotti mezője és egy névmezője , így ez a lekérdezés működni fog.

Második helyzet.

Visszaküldi azoknak az alkalmazottaknak a listáját, akiknek lejárt feladataik vannak. Így nézne ki ez a lekérdezés SQL-ben:

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

DISTINCTazért használatos, mert egy felhasználóhoz több feladat is hozzárendelhető.

És most írjuk be ugyanazt a lekérdezést HQL-ben:

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

alkalmazott ebben a lekérdezésben az EmployeeTask osztály egyik mezője

Harmadik helyzet.

Az összes ki nem osztott feladatot az igazgatóhoz rendelje. Az SQL lekérdezés így fog kinézni:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

És most írjuk be ugyanazt a lekérdezést HQL-ben:

update EmployeeTask set employee = :user where employee is null

Az utolsó kérdés a legnehezebb. Átadnunk kell az azonosítót, igazgatót, de az EmployeeTask osztály nem tartalmaz olyan mezőt, ahová azonosítót írhat, hanem egy Employee mezőt, ahol egy Employee típusú objektumhoz kell hivatkozást rendelni.

Hibernált állapotban ezt a problémát a Query objektumnak átadott lekérdezési paraméterek segítségével oldják meg. És magában a HQL-ben az ilyen paramétereket kettősponton keresztül írják: :user. De erről egy kicsit később beszélünk.