3.1 Kortlægning af afhængige enheder

I SQL kan du skrive forespørgsler ved hjælp af JOIN. Er det muligt at gøre det samme i HQL? Det korte svar er ja. Men det fulde svar vil være mere interessant.

For det første, når vi skriver en JOIN i SQL, betyder det oftest, at en tabel refererer til en anden tabel. For eksempel indeholder opgavetabellen en medarbejder_id-kolonne, der refererer til id-kolonnen i medarbejdertabellen.

Denne afhængighed kan beskrives ved hjælp af anmærkninger i Hibernate. Lad os først oprette entiteter til vores tabeller. Lad os først beskrive medarbejdertabellen:

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

Og EmployeeTask -klassen til opgavetabellen :

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

Alt er fint, men der er et forslag. Lad os se på feltet medarbejderId i det sidste eksempel:

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

Lægger du mærke til noget mærkeligt? Hvis ikke, så betyder det, at du allerede har dannet dig en måde at tænke på i SQL-sproget.

Sagen er, at vi i Java-sproget normalt beskriver en sådan afhængighed lidt anderledes:

public Employee employee;

Vi behøver ikke at angive et id , vi angiver normalt blot en variabel, der indeholder en reference til Employee- objektet . Eller gemmer null , hvis der ikke er et sådant objekt.

Og Hibernate giver os mulighed for at beskrive en sådan situation ved hjælp af annoteringer:

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

Annoteringen @ManyToOnefortæller Hibernate, at mange EmployeeTask- enheder kan henvise til én Employee- enhed .

Og annotationen @JoinColumnangiver navnet på den kolonne, hvorfra id'et vil blive taget . Alle andre nødvendige oplysninger vil blive taget fra medarbejderklassens annoteringer.

Det endelige resultat vil se således ud:

@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 Brug af join i HQL

Og lad os nu se på, hvordan man skriver forespørgsler til relaterede enheder i HQL.

Første situation.

Vi har en medarbejder (Medarbejder), og vi vil gerne have en liste over hans opgaver. Sådan ser den forespørgsel ud i SQL:

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

Og lad os nu skrive den samme forespørgsel i HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

EmployeeTask- klassen har et medarbejderfelt , og det har et navnefelt , så denne forespørgsel fungerer.

Situation to.

Returner en liste over medarbejdere, der har forfaldne opgaver. Sådan ser den forespørgsel ud i SQL:

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

DISTINCTbruges, fordi der kan være mange opgaver tildelt én bruger.

Og lad os nu skrive den samme forespørgsel i HQL:

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

medarbejder i denne forespørgsel er et felt i EmployeeTask -klassen

Situation tre.

Tildel alle ikke-tildelte opgaver til direktøren. SQL-forespørgslen vil se sådan ud:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Og lad os nu skrive den samme forespørgsel i HQL:

update EmployeeTask set employee = :user where employee is null

Den sidste forespørgsel er den sværeste. Vi skal videregive ID'et, direktør, men EmployeeTask-klassen indeholder ikke et felt, hvor du kan skrive id, i stedet indeholder det et Employee-felt, hvor du skal tildele en reference til et objekt af typen Employee.

I Hibernate løses dette problem ved hjælp af forespørgselsparametre, der sendes til Query-objektet. Og i selve HQL skrives sådanne parametre gennem et kolon: :user. Men vi vil tale om dette lidt senere.