5.1 Pelbagai bentuk komunikasi satu dengan satu

Terdapat satu lagi kes perhubungan yang menarik dan agak khusus antara dua kelas Entiti - perhubungan satu dengan satu.

Saya memanggil kes ini sangat spesifik, kerana ia lebih mengenai objek Java daripada pangkalan data. Dalam pangkalan data, hanya terdapat dua pilihan untuk perhubungan antara jadual:

  • Baris jadual mengandungi pautan ke id jadual lain.
  • Jadual perkhidmatan digunakan untuk perhubungan banyak-ke-banyak.

Dalam kes kelas Entiti, mungkin terdapat pilihan yang diterangkan oleh beberapa anotasi:

  • @Terbenam
  • OneToOne satu pihak
  • OneToOne dua hala
  • @MapsId

Di bawah ini kita akan mempertimbangkan yang paling popular daripada mereka.

5.2 Terbenam

Ngomong-ngomong, kami telah mempertimbangkan pilihan komunikasi satu dengan satu yang paling mudah - ini ialah anotasi @Embedded. Dalam kes ini, kita mempunyai dua kelas yang disimpan dalam jadual yang sama dalam pangkalan data.

Katakan kita mahu menyimpan alamat pengguna dalam kelas 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;
}

Kemudian kita hanya perlu menambah medan dengan alamat ini ke kelas Pengguna :


@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

Hibernate akan melakukan yang lain: data akan disimpan dalam satu jadual, tetapi apabila menulis pertanyaan HQL, anda perlu beroperasi pada medan kelas.

Contoh pertanyaan HQL:

select from User where address.city = 'Paris'

5.3 OneToOne Sebelah

Bayangkan keadaan sekarang: kami mempunyai pekerja meja sumber dan tugas yang merujuk kepada pekerja. Tetapi kami tahu pasti bahawa maksimum satu tugas boleh diberikan kepada seorang pengguna. Kemudian kita boleh menggunakan anotasi untuk menerangkan keadaan ini @OneToOne.

Contoh:


@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 akan memastikan bahawa bukan sahaja satu tugas mempunyai satu pengguna, tetapi juga bahawa satu pengguna mempunyai satu tugas sahaja. Jika tidak, kes ini boleh dikatakan tidak berbeza dengan @ManyToOne.

5.4 OneToOne dua hala

Pilihan sebelumnya boleh menjadi sedikit menyusahkan, kerana selalunya anda ingin menetapkan pekerja bukan sahaja untuk tugas, tetapi juga memberikan tugas kepada pekerja.

Untuk melakukan ini, anda boleh menambah medan EmployeeTask pada kelas Pekerja dan memberikan anotasi yang betul.


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
   private EmployeeTask task;
}

Penting!Jadual pekerja tidak mempunyai medan id_tugas , sebaliknya medan id_pekerja pada jadual tugas digunakan untuk mewujudkan hubungan antara jadual .

Mewujudkan sambungan antara objek kelihatan seperti ini:


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();

Untuk mengalih keluar pautan, pautan juga mesti dialih keluar daripada kedua-dua objek:


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();