5.1 Różne formy komunikacji jeden-do-jednego
Jest jeszcze jeden ciekawy i dość specyficzny przypadek relacji pomiędzy dwiema klasami Entity - relacja jeden-do-jednego.
Nazywam ten przypadek bardzo specyficznym, ponieważ dotyczy bardziej obiektów Java niż bazy danych. W bazie danych istnieją tylko dwie opcje relacji między tabelami:
- Wiersz tabeli zawiera łącze do identyfikatora innej tabeli.
- Tabela usług jest używana w relacjach wiele-do-wielu.
W przypadku klas Entity mogą istnieć opcje opisane kilkoma adnotacjami:
- @Osadzony
- Jednostronny OneToOne
- Dwustronne OneToOne
- @MapsId
Poniżej rozważymy najpopularniejsze z nich.
5.2 Osadzony
Nawiasem mówiąc, rozważaliśmy już najprostszą opcję komunikacji jeden do jednego@Embedded
- to jest adnotacja . W tym przypadku mamy dwie klasy przechowywane w tej samej tabeli w bazie danych.
Powiedzmy, że chcemy przechowywać adres użytkownika w klasie 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;
}
Następnie musimy tylko dodać pole z tym adresem do klasy User :
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@Embedded
public UserAddress address;
@Column(name="created_date")
public Date createdDate;
}
Resztą zajmie się Hibernate: dane będą przechowywane w jednej tabeli, ale podczas pisania zapytań HQL będziesz musiał operować na polach klas.
Przykład zapytania HQL:
select from User where address.city = 'Paris'
5.3 Jednostronny OneToOne
Wyobraźmy sobie teraz sytuację: mamy tabelę źródłową pracownik i zadanie, które odnosi się do pracownika. Ale wiemy na pewno, że jednemu użytkownikowi można przypisać maksymalnie jedno zadanie. Następnie możemy użyć adnotacji do opisania tej sytuacji @OneToOne
.
Przykład:
@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 zadba o to, aby nie tylko jedno zadanie miało jednego użytkownika, ale także, aby jeden użytkownik miał tylko jedno zadanie. W przeciwnym razie ten przypadek praktycznie nie różni się od @ManyToOne
.
5.4 Dwustronne umowy jeden na jeden
Poprzednia opcja może być trochę niewygodna, ponieważ często chcesz przypisać pracownika nie tylko do zadania, ale również przypisać zadanie pracownikowi.
W tym celu możesz dodać pole EmployeeTask do klasy Pracownik i nadać mu odpowiednie adnotacje.
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
private EmployeeTask task;
}
Ważny!Tabela pracowników nie zawiera pola id_zadania , zamiast tego pole id_pracownika w tabeli zadań służy do ustalania relacji między tabelami .
Nawiązanie połączenia między obiektami wygląda następująco:
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();
Aby usunąć łącze, należy również usunąć łącza z obu obiektów:
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