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 @ManyToOne
fortæller Hibernate, at mange EmployeeTask- enheder kan henvise til én Employee- enhed .
Og annotationen @JoinColumn
angiver 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();
DISTINCT
bruges, 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.
GO TO FULL VERSION