problemin tanımı

Yukarıda söylediğimiz gibi, LazyCollectionOption.EXTRA ek açıklamasının bir sorunu var - her nesne için veritabanına ayrı bir istek gerçekleştiriyor. Hibernate'e üst nesnelerimiz için tüm alt nesneleri hemen yüklemesini istediğimizi bir şekilde açıklamamız gerekiyor.

Hibernate'in geliştiricileri, bu soruna bir çözüm buldular: HQL'deki birleştirme getirme operatörü.

HQL sorgu örneği:

select distinct task from Task t left join fetch t.employee order by t.deadline

Bu sorguda, her şey aynı anda basit ve karmaşıktır. Parça parça oluşturmaya çalışalım.

seçenek 1

Tüm nesneleri indirmek istiyoruzgörev, son tarihe göre sıralandı. İşte bu isteğin nasıl görüneceği:

select task from Task t order by t.deadline

Her şey açıkken. Ama alançalışanTask sınıfının bir kısmı, EKSTRA ek açıklamasıyla açıklama eklenmiş bir Çalışanlar koleksiyonunu içerecektir . Ve bu koleksiyonun nesneleri yüklenmeyecek.

seçenek 2

Bir nesne için alt nesneleri yüklemek için Hazırda Bekletmeyi Zorlagörev.

select task from Task t join fetch t.employee order by t.deadline

Yardım ile, sorgumuzdaki Görev ve Çalışan varlıklarını açıkça bağlarız. Hibernate bunu zaten biliyor çünkü bu alanlarda @ManyToMany ek açıklamaları kullanıyoruz .

Ancak bir join fetch elde etmek için bunu bir fetch ifadesiyle tamamlamak üzere bir join ifadesine ihtiyacımız var . Talebimiz yürütüldüğünde Task.employee koleksiyonlarındaki nesnelerin veritabanından yüklenmesi gerektiğini Hibernate'e bu şekilde söyleriz.

Seçenek 3

Önceki çözümde birkaç hata var. İlk olarak, join kullandıktan sonra, SQL bize nesneleri döndürmez.görevÇalışan tablosunda kendileriyle ilişkilendirilmiş hiçbir nesnesi olmayan . İç birleştirme tam olarak böyle çalışır .

Bu nedenle, birleştirmemizi bir sol operatörle artırmamız ve onu bir sol birleştirmeye dönüştürmemiz gerekiyor . Örnek:

select task from Task t left join fetch t.employee order by t.deadline

Seçenek 4

Ama hepsi bu değil. Kodunuzda varlıklar arasındaki ilişki çok-mayıs ise, sorgu sonuçlarında tekrarlar olacaktır. aynı nesnegörevfarklı çalışanlar (Çalışan nesneleri) üzerinde bulunabilir.

Bu nedenle, yinelenen Görev nesnesinden kurtulmak için seçim sözcüğünden sonra farklı anahtar kelimeyi eklemeniz gerekir.

select distinct task from Task t left join fetch t.employee order by t.deadline

4 adımda başladığımız talebe bu şekilde geldik. Pekala, Java kodu oldukça beklenen görünecek:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
return query.list();

JOIN FETCH Sınırlamaları

Kimse mükemmel değildir. JOIN FETCH deyimi de. Oldukça az sınırlaması var. İlki setMaxResults() ve setFirstResult() metotlarını kullanmaktır .

JOIN FETCH deyimi için Hibernate'imiz, üç tabloyu tek bir tablo olarak birleştirdiğimiz çok karmaşık bir sorgu oluşturacak: çalışan, görev ve çalışan_görevi. Aslında bu, çalışanlar veya görevler için değil, bilinen tüm çalışan-görev çiftleri için bir istektir.

Ve SQL, LIMIT ve OFFSET deyimlerini tam olarak bu çalışan-görev çiftleri sorgusuna uygulayabilir. Aynı zamanda, HQL sorgusundan, tam olarak görevleri (Task) almak istediğimizi açıkça takip eder ve FirstResult ve MaxResult parametrelerimizi yeniden dağıtırsak, bunların özellikle Task nesnelerine atıfta bulunmaları gerekir.

Şöyle bir kod yazarsanız:

String hql = " select distinct task from Task t left join fetch t.employee order by t.deadline";
Query<Task> query = session.createQuery( hql, Task.class);
       	    query.setFirstResult(0);
        	   query.setMaxResults(1);
return query.list();

Ardından Hazırda Bekletme, FirstResult ve MaxResult'u SQL sorgusunun OFFSET ve LIMIT parametrelerine doğru şekilde dönüştüremez.

Bunun yerine, üç şey yapacak:

  • SQL sorgusu genel olarak tablodaki tüm verileri seçecek ve Hazırda Beklet'e döndürecektir.
  • Hibernate, hafızasındaki gerekli kayıtları seçecek ve size geri getirecektir.
  • Hazırda bekletme bir uyarı verecektir

Uyarı şöyle bir şey olacak:

WARN [org.hibernate.hql.internal.ast.QueryTranslatorImpl] HHH000104: 
firstResult/maxResults specified with collection fetch; applying in memory!