Связь на уровне таблиц
Давай опять рассмотрим две наши таблицы:
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-классы для этих таблиц – разные.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ