Зв'язок лише на рівні таблиць

Давай знову розглянемо дві наші таблиці:

id name occupation salary age join_date
1 Іванов Іван Програміст 100000 25 2012-06-30
2 Петроов Петроо Програміст 80000 23 2013-08-12
3 Іванов Сергій Тестувальник 40000 30 2014-01-01
4 Рабінович Мойша Директор 200000 35 2015-05-12
5 Кирієнко Анастасія Офіс менеджер 40000 25 2015-10-10
6 Васько Кіт 1000 3 2018-11-11

Таблиця працівника:

У цій таблиці є такі колонки:

  • id INT
  • name VARCHAR
  • occupation VARCHA
  • salary INT
  • age INT
  • join_date DATE

А так виглядає таблиця task , яка містить завдання для співробітників:

id emploee_id name deadline
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 (NULL) Прибрати офіс (NULL)
7 4 Насолоджуватися життям (NULL)
8 6 Насолоджуватися життям (NULL)

У цій таблиці є всього 4 колонки:

  • id – унікальний номер завдання (та рядки у таблиці).
  • employee_id – ID співробітника з таблиці employee, якого призначено завдання.
  • name – назва та опис завдання.
  • deadline – час, до якого потрібно виконати завдання.

Один запис таблиці employee може посилатися багато рядків таблиці task. Такий зв'язок на рівні таблиць називається одним-багатьом (one-to-many).

Зв'язок на рівень Java-класів

І наші класи, клас Employee :

@Entity
@Table(name="user")
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;
}

І клас EmployeeTask у його первісному вигляді:

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

Анотація @OneToMany

Ми можемо організувати зв'язок Entity-класів по-іншому.

Пам'ятаєш інструкцію @ElementCollection , за допомогою якої ми в батьківському класі створювали колекцію дочірніх об'єктів? Щось схоже можна зробити за допомогою анотації @OneToMany . Тільки цього разу змін піддасться клас Employee :

@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;

   @OneToMany(cascade = CascadeType.ALL)
   @JoinColumn(name = "employee_id")
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}

За допомогою інструкції @OneToMany ми вказали, що об'єктEmployeeможе зберігати багато об'єктів EmployeeTask . Також за допомогою анотації @JoinColumn ми вказали, в якій колонці таблиці task зберігається id об'єктаEmployee.

При цьому клас EmployeeTask зазвичай не містить поля, яке посилається на стовпчик employee_id. Приклад:

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String description;

   @Column(name="deadline")
   public Date deadline;
}

Поле employee_id вважається службовим та його значенням управляє Hibernate.

Приклади запитів

Якщо ти хочеш додати якомусь працівнику певний task, то тобі потрібно написати код такого:

EmployeeTask task1 = new EmployeeTask();
task1.description = "Зробити щось важливе";
session.persist(task1);

EmployeeTask task2 = new EmployeeTask();
task2.description = "Нічого не робити";
session.persist(task2);
session.flush();

Employee director = session.find(Employee.class, 4);
director.tasks.add(task1);
director.tasks.add(task2);

session.update(director);
session.flush();

Спочатку ми створюємо два об'єкти EmployeeTask , зберігаємо їх у базу і викликаємо метод flush() , щоб виконалася операція INSERT і з'явабося ID.

Потім знаходимо в базі директора, беремо в нього поле tasks та додаємо йому два завдання. Потім зберігаємо директора до бази. Після цього в базі нових task в колонці employee_id з'явиться значення 4 - id директора в таблиці employee.

Важливо! Таблиці в базі одні й самі для анотацій @ManyToOne і @OneToMany . А ось Java-класи для цих таблиць – різні.