2.1 Menghubungkait di peringkat jadual

Kami telah melihat cara Hibernate menyimpan koleksi dalam jadual tambahan. Sekarang mari kita fikirkan cara mengatur perhubungan antara jadual lengkap yang menyimpan kelas Entiti sebenar.

Terdapat empat jenis perhubungan antara kelas Entiti dalam Hibernate:

  • satu - satu
  • satu - kepada- ramai
  • banyak -ke- satu
  • banyak -ke- ramai

Dan kami akan memulakan analisis dengan pilihan yang paling mudah - banyak -ke- satu .

Anda telah pun menemui perhubungan sedemikian antara jadual dalam SQL. Inilah yang biasanya kelihatan seperti:

ID nama pekerjaan gaji umur tarikh menyertai
1 Ivanov Ivan Pengaturcara 100000 25 30-06-2012
2 Petrov Petr Pengaturcara 80000 23 2013-08-12
3 Ivanov Sergey Penguji 40000 tiga puluh 2014-01-01
4 Rabinovich Moisha Pengarah 200000 35 12-05-2015
5 Kirienko Anastasia Pengurus pejabat 40000 25 2015-10-10
6 Vaska Kucing 1000 3 2018-11-11

meja pekerja:

Jadual ini mempunyai lajur berikut:

  • id INT
  • nama VARCHAR
  • pekerjaan VARCHAR
  • gaji INT
  • umur INT
  • join_date DATE

Dan ini adalah bagaimana jadual tugas , yang mengandungi tugasan untuk pekerja, kelihatan seperti:

ID ID pekerja nama tarikh akhir
1 1 Betulkan pepijat pada bahagian hadapan 2022-06-01
2 2 Betulkan pepijat pada bahagian belakang 15-06-2022
3 5 Beli kopi 2022-07-01
4 5 Beli kopi 2022-08-01
5 5 Beli kopi 2022-09-01
6 (NULL) Bersihkan pejabat (NULL)
7 4 Nikmati kehidupan (NULL)
8 6 Nikmati kehidupan (NULL)

Jadual ini hanya mempunyai 4 lajur:

  • id – nombor tugas unik (dan baris dalam jadual);
  • id_pekerja – ID pekerja daripada jadual pekerja yang mana tugas itu diberikan;
  • nama - nama dan perihalan tugas;
  • tarikh akhir - masa di mana tugas mesti diselesaikan.

Kami melihat bahawa banyak baris dalam jadual tugas boleh merujuk kepada satu entri dalam jadual pekerja. Hubungan peringkat jadual sedemikian dipanggil banyak-dengan -satu.

2.2 Hubungan dengan peringkat kelas Java

Selain komunikasi di peringkat jadual, anda juga boleh mengatur komunikasi di peringkat kelas Entiti dalam Hibernate. Ini dilakukan dengan anotasi @ManyToOne.

Tetapi pertama-tama, mari kita buat dua kelas: Employee dan EmployeeTask :


@Entity
@Table(name="employee")
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;
}

Dan kelas kedua untuk menyimpan pekerjaan pekerja:


@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;
}

Semuanya baik dengan kelas ini, tetapi tiada hubungan antara mereka yang akan mencerminkan fakta bahawa medan employeeId kelas EmployeeTask merujuk kepada medan id kelas Pekerja. Sudah tiba masanya untuk membetulkannya

2.3 @ManyToOne anotasi.

Pertama, di Jawa kita terbiasa mengendalikan objek (dan rujukan objek) dan bukannya id mereka. Oleh itu, pertama sekali, bukannya medan employeeId dalam kelas EmployeeTask, mari kita tuding kepada objek jenis Employee. Inilah rupa kelas baharu kami:


@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
   @ManyToOne
   @JoinColumn(name = "employee_id")
   public Employee employee;
 
   @Column(name="deadline")
   public Date deadline;
}

Dengan bantuan anotasi @ManyToOne , kami telah menunjukkan bahawa banyak objek EmployeeTask boleh merujuk kepada satu objek jenis Employee. Selain itu, menggunakan anotasi @JoinColumn , kami menunjukkan dalam lajur jadual kami id objek Pekerja disimpan.

2.4 Meminta contoh

Dan sekarang mari tunjukkan beberapa contoh cara Hibernate boleh berfungsi dengan kelas yang berkaitan.

Senario satu

Mari tulis pertanyaan untuk mengetahui semua tugasan yang telah diberikan kepada pengguna tertentu. Begini rupa pertanyaan ini dalam HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Anda hanya boleh merujuk kepada medan kelas bergantung melalui titik. Ia sangat selesa. Tetapi mari kita tetap menulis pertanyaan ini dalam bentuk kod Java:


String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();

Senario kedua

Mari tulis pertanyaan yang mengembalikan senarai pekerja yang mempunyai tugas tertunggak. Sesuatu tugas tertunggak jika tarikh akhir tugasan itu sudah lewat. Begini rupa pertanyaan itu dalam SQL:


SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();

DISTINCTdigunakan kerana terdapat banyak tugasan yang diberikan kepada satu pengguna.

Dan sekarang mari kita tulis pertanyaan yang sama dalam HQL:

select distinct employee from EmployeeTask where deadline < CURDATE();

Pekerja dalam pertanyaan ini ialah medan kelas EmployeeTask

Situasi tiga

Serahkan semua tugas yang belum diserahkan kepada pengarah. Pertanyaan SQL akan kelihatan seperti ini:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Dan sekarang mari kita tulis pertanyaan yang sama dalam HQL:

update EmployeeTask set employee = :user where employee is null

Pertanyaan terakhir adalah yang paling sukar. Kita perlu lulus ID pengarah, tetapi kelas EmployeeTask tidak mengandungi medan di mana kita boleh menulis id, sebaliknya ia mengandungi medan Pekerja di mana kita perlu menetapkan rujukan kepada objek jenis Pekerja.


Employee director = session.get(Employee.class, 4);
 
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();