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