3.1 Kartlegging av avhengige enheter
I SQL kan du skrive spørringer ved å bruke JOIN. Er det mulig å gjøre det samme i HQL? Det korte svaret er ja. Men det fullstendige svaret vil være mer interessant.
For det første, når vi skriver en JOIN i SQL, betyr det oftest at en tabell refererer til en annen tabell. For eksempel inneholder oppgavetabellen en ansatt_id-kolonne som refererer til id-kolonnen i ansatttabellen.
Denne avhengigheten kan beskrives ved hjelp av merknader i dvalemodus. Først, la oss bare lage entiteter for bordene våre. La oss først beskrive ansatttabellen:
@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 for oppgavetabellen :
@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 bra, men det er ett forslag. La oss se på ansatt-ID- feltet i det siste eksemplet:
@Column(name="employee_id")
public Integer employeeId;
Merker du noe rart? Hvis ikke, betyr dette at du allerede har dannet deg en måte å tenke på i SQL-språket.
Saken er at i Java-språket beskriver vi vanligvis en slik avhengighet litt annerledes:
public Employee employee;
Vi trenger ikke spesifisere en id , vi spesifiserer vanligvis bare en variabel som inneholder en referanse til Employee- objektet . Eller lagrer null hvis det ikke finnes et slikt objekt.
Og Hibernate lar oss beskrive en slik situasjon ved å bruke merknader:
@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;
Merknaden @ManyToOne
forteller Hibernate at mange EmployeeTask- enheter kan referere til én Employee- enhet .
Og merknaden @JoinColumn
spesifiserer navnet på kolonnen som ID-en skal hentes fra . All annen nødvendig informasjon vil bli hentet fra merknadene til Ansattklassen.
Det endelige resultatet vil se slik ut:
@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 Bruke join i HQL
Og la oss nå se på hvordan du skriver spørringer til relaterte enheter i HQL.
Første situasjon.
Vi har en ansatt (Ansatt) og vi ønsker å få en liste over hans oppgaver. Slik vil spørringen se ut i SQL:
SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";
Og la oss nå skrive den samme spørringen i HQL:
from EmployeeTask where employee.name = "Ivan Ivanovich"
EmployeeTask- klassen har et ansattfelt , og den har et navnefelt , så denne spørringen vil fungere.
Situasjon to.
Returner en liste over ansatte som har forfalte oppgaver. Slik vil spørringen se ut i SQL:
SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();
DISTINCT
brukes fordi det kan være mange oppgaver tildelt én bruker.
Og la oss nå skrive den samme spørringen i HQL:
select distinct employee from EmployeeTask where deadline < CURDATE();
ansatt i denne spørringen er et felt i EmployeeTask -klassen
Situasjon tre.
Tildel alle ikke-tildelte oppgaver til direktøren. SQL-spørringen vil se slik ut:
UPDATE task SET employee_id = 4 WHERE employee_id IS NULL
Og la oss nå skrive den samme spørringen i HQL:
update EmployeeTask set employee = :user where employee is null
Det siste søket er det vanskeligste. Vi må sende ID-en, direktør, men EmployeeTask-klassen inneholder ikke et felt der du kan skrive id, i stedet inneholder den et Employee-felt hvor du må tilordne en referanse til et objekt av typen Employee.
I Hibernate løses dette problemet ved hjelp av spørringsparametere som sendes til Query-objektet. Og i selve HQL skrives slike parametere gjennom et kolon: :user
. Men vi skal snakke om dette litt senere.
GO TO FULL VERSION