Servis masası
Şimdi başka bir yaygın duruma bakalım - çoktan çoğa. Görevler ve çalışanlar arasında çoktan çoğa bir ilişkimiz olduğunu düşünelim :
- Çalışan tablosundaki bir çalışan, görev tablosundan birçok görevi yapabilir.
- Görev tablosundaki bir görev, birkaç çalışana atanabilir.
Varlıklar arasındaki bu ilişkiye çoktan çoğa denir. Ve bunu SQL seviyesinde uygulamak için ek bir servis tablosuna ihtiyacımız var. Buna örneğin, çalışan_görevi diyelim.
Çalışan_görevi tablosu yalnızca iki sütun içerecektir:
- Çalışan kimliği
- görev_kimliği
Belirli bir kullanıcıya belirli bir görev atadığımız her seferde, bu tabloya yeni bir satır eklenecektir. Örnek:
Çalışan kimliği | görev_kimliği |
---|---|
1 | 1 |
1 | 2 |
2 | 3 |
Pekala, görev tablosu çalışan_kimliği sütununu kaybetmeli . Yalnızca görev yalnızca bir çalışana atanabiliyorsa mantıklıdır. Görev birden fazla çalışana atanabiliyorsa, bu bilgi çalışan_görevi hizmet tablosunda saklanmalıdır .
Tablo Düzeyinde İlişki
Yeni tablolarımız şöyle görünecek:
İD | isim | meslek | maaş | yaş | katılmak_tarihi |
---|---|---|---|---|---|
1 | İvanov İvan | Programcı | 100000 | 25 | 2012-06-30 |
2 | Petrov Petr | Programcı | 80000 | 23 | 2013-08-12 |
3 | İvanov Sergey | test cihazı | 40000 | otuz | 2014-01-01 |
4 | Rabinovich Moisha | Müdür | 200000 | 35 | 2015-05-12 |
5 | Kirienko Anastasia | Ofis Yöneticisi | 40000 | 25 | 2015-10-10 |
6 | Vaska | Kedi | 1000 | 3 | 2018-11-11 |
Çalışan tablosu ( değişmedi ) :
Bu tablo aşağıdaki sütunlara sahiptir:
- kimlik INT
- isim VARCHAR
- meslek _
- maaş INT
- yaş INT
- katılım_tarihi DATE
Ve görev tablosu şu şekilde görünüyor , staff_id sütununu kaybetti (kırmızı ile işaretlenmiş):
İD | çalışan kimliği | isim | son teslim tarihi |
---|---|---|---|
1 | 1 | Ön uçtaki bir hatayı düzeltin | 2022-06-01 |
2 | 2 | Arka uçtaki bir hatayı düzeltin | 2022-06-15 |
3 | 5 | kahve satın al | 2022-07-01 |
4 | 5 | kahve satın al | 2022-08-01 |
5 | 5 | kahve satın al | 2022-09-01 |
6 | (HÜKÜMSÜZ) | ofisi temizle | (HÜKÜMSÜZ) |
7 | 4 | Hayatın tadını çıkar | (HÜKÜMSÜZ) |
8 | 6 | Hayatın tadını çıkar | (HÜKÜMSÜZ) |
Bu tabloda artık yalnızca 3 sütun var:
- id - benzersiz görev numarası (ve tablodaki satırlar)
- çalışan_kimliği - (kaldırıldı)
- ad - görevin adı ve açıklaması
- son tarih - görevin tamamlanması gereken süre
Ayrıca , çalışan_kimliği verilerinin görev tablosundan taşındığı bir çalışan_task hizmet tablosuna da sahibiz :
Çalışan kimliği | görev_kimliği |
---|---|
1 | 1 |
2 | 2 |
5 | 3 |
5 | 4 |
5 | 5 |
(HÜKÜMSÜZ) | 6 |
4 | 7 |
6 | 8 |
Silinen sütunu geçici olarak görev tablosuna kaydettim, böylece buradaki verilerin çalışan_görev tablosuna taşındığını görebilirsiniz.
Bir diğer önemli nokta ise staff_task tablosundaki kırmızı çizgi olan "(NULL) 6" dır. Çalışan_görevi tablosunda olmayacağı için kırmızıyla işaretledim .
Görev 7, kullanıcı 4'e atanmışsa, çalışan_görev tablosunda bir satır (4, 7) olmalıdır.
Görev 6 kimseye atanmamışsa, çalışan_görev tablosunda bunun için hiçbir kayıt olmayacaktır. İşte bu tabloların son sürümleri şöyle görünecek:
görev tablosu :
İD | isim | son teslim tarihi |
---|---|---|
1 | Ön uçtaki bir hatayı düzeltin | 2022-06-01 |
2 | Arka uçtaki bir hatayı düzeltin | 2022-06-15 |
3 | kahve satın al | 2022-07-01 |
4 | kahve satın al | 2022-08-01 |
5 | kahve satın al | 2022-09-01 |
6 | ofisi temizle | (HÜKÜMSÜZ) |
7 | Hayatın tadını çıkar | (HÜKÜMSÜZ) |
8 | Hayatın tadını çıkar | (HÜKÜMSÜZ) |
çalışan_görev tablosu:
Çalışan kimliği | görev_kimliği |
---|---|
1 | 1 |
2 | 2 |
5 | 3 |
5 | 4 |
5 | 5 |
4 | 7 |
6 | 8 |
Java sınıfı düzeyinde iletişim
Ancak Entity sınıfları seviyesindeki iletişim ile tam bir düzene sahibiz. İyi haberle başlayalım.
İlk olarak, Hibernate , çoktan çoğa tablo ilişkisini iyi bir şekilde tanımlamanıza izin veren özel bir @ManyToMany ek açıklamasına sahiptir.
İkincisi, iki Entity sınıfı bizim için hala yeterli. Servis tablosu için bir sınıfa ihtiyacımız yok.
İşte sınıflarımızın nasıl görüneceği. Özgün biçiminde Çalışan sınıfı :
@Entity
@Table(name="user")
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;
}
Ve orijinal haliyle, EmployeeTask sınıfı:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@Column(name="deadline")
public Date deadline;
}
@ManyToMany notu
Örneklerdeki mevcut alanları çıkaracağım, ancak yenilerini ekleyeceğim. İşte nasıl görünecekleri. Çalışan sınıfı :
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="employee_task",
joinColumns= @JoinColumn(name="employee_id", referencedColumnName="id"),
inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}
Ve EmployeeTask sınıfı :
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="employee_task",
joinColumns= @JoinColumn(name="task_id", referencedColumnName="id"),
inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
private Set<Employee> employees = new HashSet<Employee>();
}
Her şey karmaşık gibi görünüyor, ama aslında her şey basit.
İlk olarak, staff_task hizmet tablosunu açıklayan @JoinTable notunu (@JoinColumn ile karıştırılmamalıdır) kullanır .
İkinci olarak, staff_task tablosunun task_id sütununun görev tablosunun id sütununa atıfta bulunduğunu açıklar.
Üçüncüsü, çalışan_görev tablosunun çalışan_kimliği sütununun çalışan tablosunun kimlik sütununa atıfta bulunduğunu söylüyor.
Aslında ek açıklamalar yardımıyla, staff_task tablosunda hangi verilerin bulunduğunu ve Hibernate'in bunu nasıl yorumlaması gerektiğini açıkladık.
Ancak artık herhangi bir çalışana çok kolay bir şekilde görev ekleyebilir (ve silebiliriz). Ayrıca herhangi bir göreve herhangi bir sanatçı ekleyin.
İstek örnekleri
Bu ManyToMany alanlarının nasıl çalıştığını daha iyi anlamak için birkaç ilginç sorgu yazalım. Ve tam olarak beklendiği gibi çalışıyorlar.
İlk olarak, yönetmenin daha önce bir görev alanı olduğu için eski kodumuz değişmeden çalışacaktır:
EmployeeTask task1 = new EmployeeTask();
task1.description = "Do Something Important";
session.persist(task1);
EmployeeTask task2 = new EmployeeTask();
task2.description = "Nothing to do";
session.persist(task2);
session.flush();
Employee director = session.find(Employee.class, 4);
director.tasks.add(task1);
director.tasks.add(task2);
session.update(director);
session.flush();
İkinci olarak, bir göreve başka bir oyuncu atamak istiyorsak, bunu yapmak daha da kolaydır:
Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);
session.update(task);
session.flush();
Önemli! Bu talebin yerine getirilmesi sonucunda, sadece görevin bir yürütücü-yönetmeni olmayacak, aynı zamanda yönetmenin de 101 numaralı görevi olacaktır.
İlk olarak, çalışan_görev tablosundaki yönetici ile görev arasındaki ilişki hakkındaki gerçek bir dizi olarak saklanacaktır: (4,101).
İkincisi, @ManyToMany ek açıklamalarıyla işaretlenen alanlar proxy nesneleridir ve bunlara erişildiğinde her zaman bir veritabanı sorgusu yürütülür.
Dolayısıyla, bir çalışana bir görev eklerseniz ve çalışanla ilgili bilgileri veritabanına kaydederseniz, bundan sonra görevin yürütücüler listesinde yeni bir yürütücü olacaktır.
GO TO FULL VERSION