2.1 Tablo düzeyinde bağlantı oluşturma

Hibernate'in koleksiyonları yardımcı tablolarda nasıl sakladığını gördük. Şimdi gerçek Entity sınıflarını depolayan tam teşekküllü tablolar arasındaki ilişkilerin nasıl düzenleneceğini bulalım.

Hazırda Bekletme modunda Varlık sınıfları arasında dört tür ilişki vardır:

  • bire bir _
  • birden çoğa _
  • çok bire bir
  • çoktan çoğa _

Ve analize en basit seçenekle başlayacağız - çoktan bire .

SQL'de tablolar arasında böyle bir ilişkiye zaten rastlamışsınızdır. Genellikle şöyle görünür:

İ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:

Bu tablo aşağıdaki sütunlara sahiptir:

  • kimlik INT
  • isim VARCHAR
  • meslek _
  • maaş INT
  • yaş INT
  • katılım_tarihi DATE

Çalışanlar için görevleri içeren görev tablosu şu şekilde görünür:

İ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 yalnızca 4 sütun vardır:

  • kimlik – benzersiz görev numarası (ve tablodaki satırlar);
  • çalışan_kimliği – görevin atandığı çalışan tablosundaki çalışan kimliği;
  • isim – görevin adı ve açıklaması;
  • son tarih - görevin tamamlanması gereken süre.

Görev tablosundaki birçok satırın, çalışan tablosundaki tek bir girdiye atıfta bulunabileceğini görüyoruz. Böyle bir tablo düzeyinde ilişki, çoktan bire olarak adlandırılır .

2.2 Java sınıfı düzeyiyle ilişki

Tablo düzeyinde iletişime ek olarak, Hibernate'de Entity sınıfları düzeyinde de iletişim düzenleyebilirsiniz. Bu bir ek açıklama ile yapılır @ManyToOne.

Ama önce iki sınıf oluşturalım: Çalışan ve ÇalışanTask :


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

Ve çalışan işlerini depolamak için ikinci bir sınıf:


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

Bu sınıflarda her şey yolundadır, ancak bunlar arasında, EmployeeTask sınıfının staffId alanının, Employee sınıfının id alanına atıfta bulunduğu gerçeğini yansıtacak bir ilişki yoktur. düzeltme zamanı

2.3 @ManyToOne notu.

İlk olarak, Java'da kimlikleri yerine nesneler (ve nesne referansları) üzerinde çalışmaya alışkınız. O yüzden öncelikle, EmployeeTask sınıfındaki staffId alanı yerine, sadece Employee türünde bir nesneyi işaret edelim. İşte yeni sınıfımızın nasıl görüneceği:


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

Ek açıklamanın yardımıyla @ManyToOne, birçok Çalışan Görevi nesnesinin Çalışan türündeki tek bir nesneye başvurabileceğini belirttik. Ek açıklamayı @JoinColumn kullanarak , tablomuzun hangi sütununda Çalışan nesnesinin id'sinin saklandığını belirttik.

2.4 Talep örnekleri

Şimdi Hibernate'in bu tür ilgili sınıflarla nasıl çalışabileceğine dair bazı örnekler gösterelim.

Birinci senaryo

Belirli bir kullanıcıya atanan tüm görevleri bulmak için bir sorgu yazalım. Bu sorgunun HQL'de nasıl görüneceği aşağıda açıklanmıştır:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Bağımlı sınıfların alanlarına bir nokta ile basitçe başvurabilirsiniz. Çok rahat. Ama yine de bu sorguyu Java kodu biçiminde yazalım:


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

İkinci senaryo

Vadesi geçmiş görevleri olan çalışanların listesini döndüren bir sorgu yazalım. Son teslim tarihi geçmişse, bir görevin süresi geçmiş demektir. İşte bu sorgunun SQL'de nasıl görüneceği:


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

DISTINCTBir kullanıcıya atanan birçok görev olabileceği için kullanılır.

Şimdi aynı sorguyu HQL'de yazalım:

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

Bu sorgudaki Çalışan, EmployeeTask sınıfının bir alanıdır

Durum üç

Atanmamış tüm görevleri yöneticiye atayın. SQL sorgusu şöyle görünecektir:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Şimdi aynı sorguyu HQL'de yazalım:

update EmployeeTask set employee = :user where employee is null

Son sorgu en zor olanıdır. Direktöre ait ID'yi iletmemiz gerekiyor fakat EmployeeTask sınıfında id yazabileceğimiz bir alan yok bunun yerine Employee tipinde bir nesneye referans atamamız gereken Çalışan alanı var.


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