Связь на уровне таблиц

Давай опять рассмотрим две наши таблицы:

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

Таблица employee:

В этой таблице есть такие колонки:

  • 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-классы для этих таблиц – разные.

undefined
1
Задача
Модуль 4. Работа с БД, 13 уровень, 2 лекция
Недоступна
Автор книги или книга автора?
Есть три класса-энтити: Author, Book и Publisher, и таблицы, которые им соответствуют...