2.1 Összekapcsolás asztali szinten
Láttuk, hogyan tárolja a Hibernate a gyűjteményeket a segédtáblázatokban. Most nézzük meg, hogyan lehet kapcsolatokat megszervezni a valódi entitásosztályokat tároló teljes értékű táblák között.
Négy típusú kapcsolat létezik a hibernált entitásosztályok között:
- egy az egyhez
- egy a sokhoz
- sok -az- egyhez
- sok -sok _
És az elemzést a legegyszerűbb lehetőséggel kezdjük – sok az egyhez .
SQL-ben már találkoztál ilyen táblák közötti kapcsolattal. Általában így néz ki:
id | név | Foglalkozása | fizetés | kor | csatlakozás dátuma |
---|---|---|---|---|---|
1 | Ivanov Iván | Programozó | 100 000 | 25 | 2012-06-30 |
2 | Petrov Petr | Programozó | 80000 | 23 | 2013-08-12 |
3 | Ivanov Szergej | Vizsgáló | 40000 | harminc | 2014-01-01 |
4 | Rabinovics Moisa | Rendező | 200 000 | 35 | 2015-05-12 |
5 | Kirienko Anasztázia | Irodavezető | 40000 | 25 | 2015-10-10 |
6 | Vaska | Macska | 1000 | 3 | 2018-11-11 |
alkalmazotti táblázat:
Ez a táblázat a következő oszlopokat tartalmazza:
- azonosító INT
- név VARCHAR
- foglalkozás VARCHAR
- fizetés INT
- kor INT
- csatlakozási_dátum DATE
Így néz ki az alkalmazottak feladatait tartalmazó feladattábla :
id | munkavállalói azonosító | név | határidő |
---|---|---|---|
1 | 1 | Javítson ki egy hibát a kezelőfelületen | 2022-06-01 |
2 | 2 | Javítson ki egy hibát a háttérben | 2022-06-15 |
3 | 5 | Vegyél kávét | 2022-07-01 |
4 | 5 | Vegyél kávét | 2022-08-01 |
5 | 5 | Vegyél kávét | 2022-09-01 |
6 | (NULLA) | Takarítsd ki az irodát | (NULLA) |
7 | 4 | Élvezd az életet | (NULLA) |
8 | 6 | Élvezd az életet | (NULLA) |
Ez a táblázat csak 4 oszlopot tartalmaz:
- id – egyedi feladatszám (és sorok a táblázatban);
- munkavállaló_azonosítója – alkalmazott azonosítója abból az alkalmazotti táblából, amelyhez a feladat hozzá van rendelve;
- név – a feladat megnevezése és leírása;
- határidő - az az idő, ameddig a feladatot el kell végezni.
Látjuk, hogy a feladattábla sok sora hivatkozhat egyetlen bejegyzésre az alkalmazotti táblában. Az ilyen táblaszintű kapcsolatot sok- egyhez nevezzük.
2.2 Kapcsolat a Java osztályszinttel
Az asztali szintű kommunikáció mellett a hibernált Entity osztályok szintjén is megszervezheti a kommunikációt. Ez annotációval történik @ManyToOne
.
De először csak hozzunk létre két osztályt: Employee és EmployeeTask :
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@Column(name="name")
public String name;
@Column(name="occupation")
public String occupation;
@Column(name="salary")
public Integer salary;
@Column(name="join_date")
public Date join;
}
És egy második osztály az alkalmazotti munkák tárolására:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@Column(name="employee_id")
public Integer employeeId;
@Column(name="deadline")
public Date deadline;
}
Ezekkel az osztályokkal minden rendben van, de nincs közöttük olyan kapcsolat, amely azt tükrözné, hogy az EmployeeTask osztály workerId mezője az Employee osztály id mezőjére utal. Ideje megjavítani
2.3 @ManyToOne megjegyzés.
Először is, a Java-ban megszoktuk, hogy objektumokkal (és objektumhivatkozásokkal) kell dolgozni, nem pedig az azonosítójukkal. Tehát mindenekelőtt az EmployeeTask osztály munkavállalóazonosító mezője helyett mutassunk egy Employee típusú objektumra. Így fog kinézni az új osztályunk:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@ManyToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
Az annotáció segítségével @ManyToOne
jeleztük, hogy sok EmployeeTask objektum hivatkozhat egy Employee típusú objektumra. Továbbá az annotáció @JoinColumn
segítségével jeleztük, hogy táblázatunk melyik oszlopában van tárolva az Employee objektum azonosítója.
2.4 Példák kérése
Most pedig mutassunk néhány példát arra, hogyan tud a Hibernate együttműködni az ilyen kapcsolódó osztályokkal.
Egy forgatókönyv
Írjunk lekérdezést, hogy megtudjuk az összes olyan feladatot, amelyet egy adott felhasználóhoz rendeltek. Így nézne ki ez a lekérdezés HQL-ben:
from EmployeeTask where employee.name = "Ivan Ivanovich"
Egyszerűen egy ponton keresztül hivatkozhat a függő osztályok mezőire. Nagyon kényelmes. De írjuk meg ezt a lekérdezést Java kód formájában:
String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
Második forgatókönyv
Írjunk egy lekérdezést, amely visszaadja azon alkalmazottak listáját, akiknek lejárt feladataik vannak. Egy feladat lejárt, ha a határideje a múltban van. Í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();
DISTINCT
azé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();
Az Employee 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 igazgató azonosítóját, de az EmployeeTask osztály nem tartalmaz olyan mezőt, ahová azonosítót írhatunk, hanem egy Employee mezőt, ahol egy Employee típusú objektumhoz kell hivatkozást rendelnünk.
Employee director = session.get(Employee.class, 4);
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();
GO TO FULL VERSION