@wielu na jeden

Dostępny

2.1 Łączenie na poziomie tabeli

Widzieliśmy, jak Hibernate przechowuje kolekcje w tabelach pomocniczych. Teraz zastanówmy się, jak zorganizować relacje między pełnoprawnymi tabelami, które przechowują prawdziwe klasy Entity.

Istnieją cztery typy relacji między klasami jednostek w Hibernate:

  • jeden do jednego
  • jeden do wielu
  • wiele do jednego
  • wiele do wielu

A analizę zaczniemy od najprostszej opcji – wiele do jednego .

Spotkałeś się już z taką zależnością między tabelami w SQL. Oto jak zwykle wygląda:

ID nazwa zawód wynagrodzenie wiek data_dołączenia
1 Iwanow Iwan Programista 100000 25 2012-06-30
2 Pietrow Pietr Programista 80000 23 2013-08-12
3 Iwanow Siergiej Próbnik 40000 trzydzieści 2014-01-01
4 Rabinowicz Mojsza Dyrektor 200000 35 2015-05-12
5 Kirienko Anastazja Kierownik biura 40000 25 2015-10-10
6 Vaska Kot 1000 3 2018-11-11

stół pracowniczy:

Ta tabela ma następujące kolumny:

  • identyfikator INT
  • imię VARCHAR
  • zawód VARCHAR
  • wynagrodzenie INT
  • wiek INT
  • data_dołączenia DATA

A tak wygląda tabela zadań , która zawiera zadania dla pracowników:

ID dowód pracownika nazwa termin ostateczny
1 1 Napraw błąd w interfejsie użytkownika 2022-06-01
2 2 Napraw błąd w backendzie 2022-06-15
3 5 Kup kawę 2022-07-01
4 5 Kup kawę 2022-08-01
5 5 Kup kawę 2022-09-01
6 (ZERO) Posprzątaj biuro (ZERO)
7 4 Ciesz się życiem (ZERO)
8 6 Ciesz się życiem (ZERO)

Ta tabela ma tylko 4 kolumny:

  • id – unikalny numer zadania (i wierszy w tabeli);
  • id_pracownika – identyfikator pracownika z tabeli pracowników, do którego zadanie jest przypisane;
  • nazwa – nazwa i opis zadania;
  • termin – czas, w jakim zadanie musi zostać wykonane.

Widzimy, że wiele wierszy w tabeli zadań może odnosić się do pojedynczego wpisu w tabeli pracowników. Taka relacja na poziomie tabeli nazywa się wiele do jednego.

2.2 Związek z poziomem klasy Java

Poza komunikacją na poziomie tabeli, można również zorganizować komunikację na poziomie klas Entity w Hibernate. Odbywa się to za pomocą adnotacji @ManyToOne.

Ale najpierw utwórzmy dwie klasy: Employee i 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;
}

I druga klasa do przechowywania zadań pracowników:

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

Z tymi klasami wszystko jest w porządku, ale nie ma między nimi związku, który odzwierciedlałby fakt, że pole EmployeeId klasy EmployeeTask odnosi się do pola id klasy Employee. Czas to naprawić

2.3 Adnotacja @ManyToOne.

Po pierwsze, w Javie jesteśmy przyzwyczajeni do operowania na obiektach (i referencjach do obiektów), a nie na ich id. Po pierwsze, zamiast pola EmployeeId w klasie EmployeeTask wskażmy po prostu obiekt typu Employee. Oto jak będzie wyglądać nasza nowa klasa:

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

Za pomocą adnotacji @ManyToOne wskazaliśmy, że wiele obiektów EmployeeTask może odnosić się do jednego obiektu typu Pracownik. Również za pomocą adnotacji @JoinColumn wskazaliśmy w której kolumnie naszej tabeli przechowywane jest id obiektu Employee.

2.4 Poproś o przykłady

A teraz pokażmy kilka przykładów, jak Hibernate może współpracować z takimi pokrewnymi klasami.

Scenariusz pierwszy

Napiszmy zapytanie, aby znaleźć wszystkie zadania, które zostały przypisane do określonego użytkownika. Oto jak wyglądałoby to zapytanie w HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Możesz po prostu odwołać się do pól klas zależnych za pomocą kropki. To jest bardzo wygodne. Ale nadal napiszmy to zapytanie w postaci kodu Java:

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

Scenariusz drugi

Napiszmy zapytanie, które zwróci listę pracowników, którzy mają zaległe zadania. Zadanie jest opóźnione, jeśli jego termin przypada w przeszłości. Oto jak wyglądałoby to zapytanie w SQL:

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

DISTINCTjest używany, ponieważ do jednego użytkownika można przypisać wiele zadań.

A teraz napiszmy to samo zapytanie w HQL:

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

Pracownik w tym zapytaniu jest polem klasy EmployeeTask

Sytuacja trzecia

Przydziel wszystkie nieprzypisane zadania dyrektorowi. Zapytanie SQL będzie wyglądać następująco:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

A teraz napiszmy to samo zapytanie w HQL:

update EmployeeTask set employee = :user where employee is null

Ostatnie zapytanie jest najtrudniejsze. Musimy przekazać identyfikator dyrektora, ale klasa EmployeeTask nie zawiera pola, w którym możemy wpisać id, zamiast tego zawiera pole Pracownik, w którym musimy przypisać referencję do obiektu typu Pracownik.

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();
Komentarze
  • Popularne
  • Najnowsze
  • Najstarsze
Musisz się zalogować, aby dodać komentarz
Ta strona nie ma jeszcze żadnych komentarzy