5.1 Различни форми на комуникация един към един
Има още един интересен и доста специфичен случай на връзка между два класа Entity - връзка едно към едно.
Наричам този случай много специфичен, тъй като става въпрос повече за Java обекти, отколкото за база данни. В базата данни има само две опции за връзката между таблиците:
- Редът на tableта съдържа връзка към идентификатора на друга table.
- Сервизната table се използва за релации много към много.
В случай на класове Entity може да има опции, които са описани с няколко анотации:
- @Вграден
- Едностранно OneToOne
- Двустранен OneToOne
- @MapsId
По-долу ще разгледаме най-популярните от тях.
5.2 Вграден
Между другото, вече разгледахме най -простата опция за комуникация един към един@Embedded
- това е анотация . В този случай имаме два класа, съхранени в една и съща table в базата данни.
Да кажем, че искаме да съхраним address на потребителя в класа UserAddress :
@Embeddable
class UserAddress {
@Column(name="user_address_country")
public String country;
@Column(name="user_address_city")
public String city;
@Column(name="user_address_street")
public String street;
@Column(name="user_address_home")
public String home;
}
След това просто трябва да добавим поле с този address към потребителския клас :
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@Embedded
public UserAddress address;
@Column(name="created_date")
public Date createdDate;
}
Hibernate ще свърши останалото: данните ще се съхраняват в една table, но когато пишете HQL заявки, ще трябва да работите с полета на класа.
Пример за HQL заявка:
select from User where address.city = 'Paris'
5.3 Едностранно един към един
Представете си сега ситуацията: имаме изходна table employee и задача, която се отнася до служител. Но знаем със сигурност, че на един потребител може да бъде възложена максимум една задача. Тогава можем да използваме анотацията, за да опишем тази ситуация @OneToOne
.
Пример:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@OneToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
Hibernate ще гарантира, че не само една задача има един потребител, но и че един потребител има само една задача. В противен случай този случай практически не се различава от @ManyToOne
.
5.4 Двустранно един към един
Предишната опция може да бъде малко неудобна, защото често искате да възложите служител не само на задача, но и да възложите задача на служител.
За да направите това, можете да добавите полето EmployeeTask към класа Employee и да му дадете правилните анотации.
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
private EmployeeTask task;
}
важно!Таблицата на служителите няма поле task_id , instead of това полето employee_id на tableта със задачи се използва за установяване на връзка между таблиците .
Установяването на връзка между обекти изглежда така:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employee = director;
director.task = task;
session.update(task);
session.flush();
За да премахнете връзката, връзките трябва да бъдат премахнати и от двата обекта:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.task;
task.employee = null;
session.update(task);
director.task = null;
session.update(director);
session.flush();
GO TO FULL VERSION