2.1 Pag-uugnay sa antas ng talahanayan

Nakita namin kung paano iniimbak ng Hibernate ang mga koleksyon sa mga auxiliary table. Ngayon, alamin natin kung paano ayusin ang mga ugnayan sa pagitan ng mga ganap na talahanayan na nag-iimbak ng mga tunay na klase ng Entity.

Mayroong apat na uri ng mga ugnayan sa pagitan ng mga klase ng Entity sa Hibernate:

  • isa -sa- isa
  • isa -sa- marami
  • marami -sa- isa
  • marami -sa- marami

At sisimulan natin ang pagsusuri gamit ang pinakasimpleng opsyon - many -to- one .

Nakatagpo ka na ng ganitong relasyon sa pagitan ng mga talahanayan sa SQL. Narito ang karaniwang hitsura nito:

id pangalan hanapbuhay suweldo edad Sumali sa date
1 Ivanov Ivan Programmer 100000 25 2012-06-30
2 Petrov Petr Programmer 80000 23 2013-08-12
3 Ivanov Sergey Tester 40000 tatlumpu 2014-01-01
4 Rabinovich Moisha Direktor 200000 35 2015-05-12
5 Kirienko Anastasia Tagapamahala ng Opisina 40000 25 2015-10-10
6 Vaska Pusa 1000 3 2018-11-11

talahanayan ng empleyado:

Ang talahanayang ito ay may mga sumusunod na column:

  • id INT
  • pangalan VARCHAR
  • hanapbuhay VARCHAR
  • suweldo INT
  • edad INT
  • join_date DATE

At ganito ang hitsura ng talahanayan ng gawain , na naglalaman ng mga gawain para sa mga empleyado:

id employee_id pangalan deadline
1 1 Ayusin ang isang bug sa frontend 2022-06-01
2 2 Ayusin ang isang bug sa backend 2022-06-15
3 5 Bumili ng kape 2022-07-01
4 5 Bumili ng kape 2022-08-01
5 5 Bumili ng kape 2022-09-01
6 (WALA) Linisin ang opisina (WALA)
7 4 Masiyahan sa buhay (WALA)
8 6 Masiyahan sa buhay (WALA)

Ang talahanayang ito ay may 4 na column lamang:

  • id – natatanging numero ng gawain (at mga hilera sa talahanayan);
  • employee_id - ID ng empleyado mula sa talahanayan ng empleyado kung saan itinalaga ang gawain;
  • pangalan - pangalan at paglalarawan ng gawain;
  • deadline - ang oras kung kailan dapat makumpleto ang gawain.

Nakikita namin na maraming mga row sa talahanayan ng gawain ang maaaring sumangguni sa isang entry sa talahanayan ng empleyado. Ang ganitong relasyon sa antas ng talahanayan ay tinatawag na many-to -one.

2.2 Relasyon sa antas ng klase ng Java

Bilang karagdagan sa komunikasyon sa antas ng talahanayan, maaari mo ring ayusin ang komunikasyon sa antas ng mga klase ng Entity sa Hibernate. Ginagawa ito gamit ang isang anotasyon @ManyToOne.

Ngunit una, gumawa lang tayo ng dalawang klase: Employee at 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;
}

At pangalawang klase para mag-imbak ng mga trabaho ng empleyado:


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

Maayos ang lahat sa mga klaseng ito, ngunit walang ugnayan sa pagitan ng mga ito na magpapakita ng katotohanan na ang field ng employeeId ng klase ng EmployeeTask ay tumutukoy sa field ng id ng klase ng Employee. Oras na para ayusin ito

2.3 @ManyToOne annotation.

Una, sa Java kami ay nakasanayan na mag-operate sa mga bagay (at object reference) kaysa sa kanilang id. Kaya una sa lahat, sa halip na ang employeeId field sa EmployeeTask class, ituro na lang natin ang isang object ng uri ng Employee. Narito ang magiging hitsura ng aming bagong klase:


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

Sa tulong ng anotasyon @ManyToOne , ipinahiwatig namin na maraming EmployeeTask object ang maaaring tumukoy sa isang object ng uri ng Empleyado. Gayundin, gamit ang anotasyon @JoinColumn , ipinahiwatig namin sa kung aling column ng aming talahanayan ang id ng object ng Empleyado ay nakaimbak.

2.4 Humiling ng mga halimbawa

At ngayon magpakita tayo ng ilang halimbawa kung paano gumagana ang Hibernate sa mga kaugnay na klase.

Unang senaryo

Sumulat tayo ng isang query upang malaman ang lahat ng mga gawain na itinalaga sa isang partikular na user. Narito ang magiging hitsura ng query na ito sa HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Maaari ka lamang sumangguni sa mga patlang ng mga umaasa na klase sa pamamagitan ng isang tuldok. Ito ay napaka komportable. Ngunit isulat pa rin natin ang query na ito sa anyo ng Java code:


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();

Pangalawang senaryo

Sumulat tayo ng query na nagbabalik ng listahan ng mga empleyadong may mga overdue na gawain. Ang isang gawain ay overdue kung ang deadline nito ay nasa nakaraan. Narito kung ano ang magiging hitsura ng query na iyon sa SQL:


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

DISTINCTay ginagamit dahil maaaring maraming gawain na nakatalaga sa isang user.

At ngayon isulat natin ang parehong query sa HQL:

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

Ang empleyado sa query na ito ay isang field ng EmployeeTask class

Pangatlong sitwasyon

Italaga ang lahat ng hindi nakatalagang gawain sa direktor. Ang SQL query ay magiging ganito:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

At ngayon isulat natin ang parehong query sa HQL:

update EmployeeTask set employee = :user where employee is null

Ang huling query ang pinakamahirap. Kailangan naming ipasa ang ID ng direktor, ngunit ang klase ng EmployeeTask ay hindi naglalaman ng isang field kung saan maaari kaming magsulat ng isang id, sa halip ay naglalaman ito ng isang field ng Empleyado kung saan kailangan naming magtalaga ng isang reference sa isang object ng uri ng Empleyado.


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();