Deskripsi masalah

Seperti yang kami katakan di atas, anotasi LazyCollectionOption.EXTRA memiliki masalah - ia melakukan permintaan terpisah ke database untuk setiap objek. Kita perlu menjelaskan kepada Hibernasi bahwa kita ingin segera memuat semua objek anak untuk objek induk kita.

Pengembang Hibernate telah menemukan solusi untuk masalah ini, operator pengambilan gabungan di HQL.

Contoh kueri HQL:

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

Dalam kueri ini, semuanya sederhana dan kompleks pada saat bersamaan. Mari kita coba membangunnya sepotong demi sepotong.

Pilihan 1

Kami ingin mengunduh semua objektugas, diurutkan berdasarkan tenggat waktu. Seperti inilah permintaan itu:

select task from Task t order by t.deadline

Sementara semuanya jelas. Tapi lapangankaryawankelas Tugas akan berisi kumpulan Karyawan yang dianotasi dengan anotasi EXTRA . Dan objek koleksi ini tidak akan dimuat.

pilihan 2

Paksa Hibernasi untuk memuat objek anak untuk suatu objektugas.

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

Dengan bantuan, kami secara eksplisit mengikat entitas Tugas dan Karyawan dalam kueri kami. Hibernasi sudah mengetahui hal ini karena kami menggunakan anotasi @ManyToMany pada kolom ini.

Tapi kita membutuhkan pernyataan gabungan untuk melengkapinya dengan pernyataan pengambilan untuk mendapatkan pengambilan gabungan . Ini adalah cara kami memberi tahu Hibernate bahwa objek dalam koleksi Task.employee perlu dimuat dari database saat permintaan kami dijalankan.

Opsi 3

Solusi sebelumnya memiliki beberapa bug. Pertama, setelah menggunakan join, SQL tidak akan mengembalikan objek kepada kitatugas, yang tidak memiliki objek yang terkait dengannya di tabel Karyawan. Inilah cara kerja gabung dalam .

Jadi kita perlu menambah gabungan kita dengan operator kiri dan mengubahnya menjadi gabungan kiri . Contoh:

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

Opsi 4

Tapi itu belum semuanya. Jika dalam kode Anda hubungan antar entitas banyak hingga Mei, maka akan ada duplikat dalam hasil kueri. Objek yang samatugasdapat ditemukan pada karyawan yang berbeda (objek Karyawan).

Jadi, Anda perlu menambahkan kata kunci yang berbeda setelah kata pilih untuk menyingkirkan objek Tugas duplikat.

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

Beginilah dalam 4 langkah kami sampai pada permintaan yang kami mulai. Nah, kode Java akan terlihat sangat diharapkan:

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

BERGABUNG MENGAMBIL Batasan

Tidak ada yang sempurna. JOIN FETCH pernyataan juga. Ini memiliki beberapa keterbatasan. Dan yang pertama menggunakan metode setMaxResults() dan setFirstResult() .

Untuk pernyataan JOIN FETCH, Hibernasi kami akan menghasilkan kueri yang sangat kompleks di mana kami menggabungkan tiga tabel menjadi satu: karyawan, tugas, dan tugas_karyawan. Sebenarnya, ini bukan permintaan untuk karyawan atau tugas, tetapi untuk semua pasangan tugas-karyawan yang dikenal.

Dan SQL dapat menerapkan pernyataan LIMIT dan OFFSET-nya ke kueri pasangan tugas-karyawan itu dengan tepat. Pada saat yang sama, jelas mengikuti dari kueri HQL bahwa kami ingin mendapatkan tugas (Tugas) yang tepat, dan jika kami mendistribusikan ulang parameter FirstResult dan MaxResult kami, maka mereka harus merujuk secara khusus ke objek Tugas.

Jika Anda menulis kode seperti ini:

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

Maka Hibernate tidak akan dapat mengonversi FirstResult dan MaxResult dengan benar ke parameter OFFSET dan LIMIT dari kueri SQL.

Sebaliknya, itu akan melakukan tiga hal:

  • Kueri SQL akan memilih secara umum semua data dari tabel dan mengembalikannya ke Hibernasi
  • Hibernasi akan memilih catatan yang diperlukan dalam memorinya dan mengembalikannya kepada Anda
  • Hibernasi akan mengeluarkan peringatan

Peringatannya akan seperti ini:

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