@ManyToOne

На разположение

2.1 Свързване на ниво table

Видяхме How Hibernate съхранява колекции в помощни таблици. Сега нека разберем How да организираме връзки между пълноценни таблици, които съхраняват реални класове Entity.

Има четири типа връзки между класовете Entity в Hibernate:

  • едно към едно
  • един към много
  • много към едно
  • много към много

И ще започнем анализа с най-простия вариант - много към едно .

Вече сте срещали такава връзка между таблици в SQL. Ето How изглежда обикновено:

document за самоличност име професия заплата възраст дата на присъединяване
1 Ivanов Ivan Програмист 100 000 25 2012-06-30
2 Peterов Петър Програмист 80 000 23 2013-08-12
3 Ivanов Сергей Тестер 40 000 тридесет 2014-01-01
4 Рабинович Мойша Директор 200 000 35 2015-05-12
5 Кириенко Анастасия Офис мениджър 40 000 25 2015-10-10
6 Васка котка 1000 3 2018-11-11

маса на служителите:

Тази table има следните колони:

  • id INT
  • име VARCHAR
  • професия VARCHAR
  • заплата INT
  • възраст INT
  • дата на присъединяване ДАТА

Ето How изглежда tableта със задачи , която съдържа задачи за служителите:

document за самоличност ИД на служител име краен срок
1 1 Коригиране на грешка във фронтенда 2022-06-01
2 2 Коригиране на грешка в бекенда 2022-06-15
3 5 Купи кафе 2022-07-01
4 5 Купи кафе 2022-08-01
5 5 Купи кафе 2022-09-01
6 (НУЛА) Почистете офиса (НУЛА)
7 4 Наслаждавай се на живота (НУЛА)
8 6 Наслаждавай се на живота (НУЛА)

Тази table има само 4 колони:

  • id – уникален номер на задача (и редове в tableта);
  • employee_id – идентификатор на служител от tableта на служителите, към който е назначена задачата;
  • име – име и описание на задачата;
  • краен срок - времето, до което задачата трябва да бъде изпълнена.

Виждаме, че много редове в tableта на задачите могат да се отнасят до един запис в tableта на служителите. Такава връзка на ниво table се нарича много към едно.

2.2 Връзка с нивото на Java клас

В допълнение към комуникацията на ниво table, можете също да организирате комуникация на ниво класове Entity в Hibernate. Това става с анотация @ManyToOne.

Но първо, нека просто създадем два класа: Employee и 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;
}

И втори клас за съхранение на работни места на служители:

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

Всичко е наред с тези класове, но няма връзка между тях, която да отразява факта, че полето employeeId на класа EmployeeTask препраща към полето id на класа Employee. Време е да го поправим

2.3 Анотация @ManyToOne.

Първо, в Java сме свикнали да работим с обекти (и препратки към обекти), а не с техния идентификатор. Така че първо, instead of полето EmployeeId в класа EmployeeTask, нека просто посочим обект от тип Employee. Ето How ще изглежда нашият нов клас:

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

С помощта на анотацията @ManyToOne сме посочor, че много обекти EmployeeTask могат да препращат към един обект от тип Employee. Също така, използвайки анотацията @JoinColumn , посочихме в коя колона на нашата table се съхранява идентификаторът на обекта Employee.

2.4 Примери за заявки

А сега нека покажем няколко примера за това How Hibernate може да работи с такива свързани класове.

Сценарий първи

Нека напишем заявка, за да разберем всички задачи, които са възложени на конкретен потребител. Ето How ще изглежда тази заявка в HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Можете просто да препращате към полета на зависими класове чрез точка. Много е удобно. Но нека все пак напишем тази заявка под формата на 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();

Сценарий две

Нека напишем заявка, която връща списък със служители, които имат просрочени задачи. Една задача е просрочена, ако нейният краен срок е в миналото. Ето How ще изглежда тази заявка в SQL:

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

DISTINCTсе използва, защото може да има много задачи, възложени на един потребител.

А сега нека напишем същата заявка в HQL:

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

Employee в тази заявка е поле от класа EmployeeTask

Ситуация трета

Възложете всички невъзложени задачи на директора. SQL заявката ще изглежда така:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

А сега нека напишем същата заявка в HQL:

update EmployeeTask set employee = :user where employee is null

Последното запитване е най-трудното. Трябва да предадем идентификатора на директора, но класът EmployeeTask не съдържа поле, където можем да напишем идентификатор, instead of това съдържа поле Employee, където трябва да присвоим препратка към обект от тип Employee.

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();
Коментари
  • Популярен
  • Нов
  • Стар
Трябва да сте влезли, за да оставите коментар
Тази страница все още няма коментари