3.1 Kartläggning av beroende enheter
I SQL kan du skriva frågor med JOIN. Är det möjligt att göra samma sak i HQL? Det korta svaret är ja. Men det fullständiga svaret blir mer intressant.
För det första, när vi skriver en JOIN i SQL betyder det oftast att en tabell refererar till en annan tabell. Till exempel innehåller uppgiftstabellen en anställd_id-kolumn som hänvisar till id-kolumnen i anställdtabellen.
Detta beroende kan beskrivas med anteckningar i Hibernate. Låt oss först skapa entiteter för våra tabeller. Låt oss först beskriva personaltabellen:
@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;
}
Och EmployeeTask -klassen för uppgiftstabellen :
@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;
}
Allt är bra, men det finns ett förslag. Låt oss titta på fältet anställd-ID i det sista exemplet:
@Column(name="employee_id")
public Integer employeeId;
Märker du något konstigt? Om inte, så betyder det att du redan har bildat ett sätt att tänka i SQL-språket.
Saken är den att i Java-språket brukar vi beskriva ett sådant beroende lite annorlunda:
public Employee employee;
Vi behöver inte ange ett id , vi brukar bara specificera en variabel som innehåller en referens till Employee -objektet . Eller lagrar null om det inte finns något sådant objekt.
Och Hibernate låter oss beskriva en sådan situation med hjälp av kommentarer:
@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;
Anteckningen @ManyToOne
talar om för Hibernate att många EmployeeTask- enheter kan hänvisa till en Employee- enhet .
Och anteckningen @JoinColumn
anger namnet på den kolumn som id:t kommer ifrån . All annan nödvändig information kommer att hämtas från anteckningarna för klassen Anställd.
Det slutliga resultatet kommer att se ut så här:
@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 Använda join i HQL
Och låt oss nu titta på hur man skriver frågor till relaterade enheter i HQL.
Första situationen.
Vi har en anställd (Anställd) och vi vill få en lista över hans arbetsuppgifter. Så här skulle den frågan se ut i SQL:
SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";
Och låt oss nu skriva samma fråga i HQL:
from EmployeeTask where employee.name = "Ivan Ivanovich"
Klassen EmployeeTask har ett anställdsfält och det har ett namnfält , så den här frågan kommer att fungera.
Situation två.
Returnera en lista över anställda som har försenade uppgifter. Så här skulle den frågan se ut i SQL:
SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();
DISTINCT
används eftersom det kan vara många uppgifter tilldelade en användare.
Och låt oss nu skriva samma fråga i HQL:
select distinct employee from EmployeeTask where deadline < CURDATE();
anställd i den här frågan är ett fält i klassen EmployeeTask
Situation tre.
Tilldela alla otilldelade uppgifter till regissören. SQL-frågan kommer att se ut så här:
UPDATE task SET employee_id = 4 WHERE employee_id IS NULL
Och låt oss nu skriva samma fråga i HQL:
update EmployeeTask set employee = :user where employee is null
Den sista frågan är den svåraste. Vi måste skicka ID:t, director, men EmployeeTask-klassen innehåller inte ett fält där du kan skriva id, istället innehåller den ett Employee-fält där du behöver tilldela en referens till ett objekt av typen Employee.
I Hibernate löses detta problem med hjälp av frågeparametrar som skickas till Query-objektet. Och i själva HQL skrivs sådana parametrar genom ett kolon: :user
. Men vi kommer att prata om detta lite senare.
GO TO FULL VERSION