Ini sebenarnya adalah perilaku yang diharapkan jika saya memahami konfigurasi Anda dengan benar.
Hibernate tidak mengembalikan hasil yang berbeda untuk kueri dengan pengambilan gabungan luar diaktifkan untuk koleksi (meskipun saya menggunakan kata kunci yang berbeda)? Pertama, Anda perlu memahami SQL dan cara kerja OUTER JOIN di SQL. Jika Anda tidak sepenuhnya memahami dan memahami gabungan luar dalam SQL, jangan lanjutkan membaca item FAQ ini tetapi lihat manual atau tutorial SQL. Jika tidak, Anda tidak akan memahami penjelasan berikut dan Anda akan mengeluh tentang perilaku ini di forum Hibernate.
Contoh umum yang mungkin mengembalikan referensi duplikat dari objek Order yang sama:
List result = session.createCriteria(Order.class)
.setFetchMode("lineItems", FetchMode.JOIN)
.list();
<class name="Order">
...
<set name="lineItems" fetch="join">
List result = session.createCriteria(Order.class)
.list();
List result = session.createQuery("select o from Order o left join fetch o.lineItems").list();
Semua contoh ini menghasilkan pernyataan SQL yang sama:
SELECT o.*, l.* from ORDER o LEFT OUTER JOIN LINE_ITEMS l ON o.ID = l.ORDER_ID
Ingin tahu mengapa duplikatnya ada? Lihatlah set hasil SQL, Hibernate tidak menyembunyikan duplikat ini di sisi kiri hasil gabungan luar tetapi mengembalikan semua duplikat dari tabel penggerak. Jika Anda memiliki 5 pesanan dalam database, dan setiap pesanan memiliki 3 item baris, kumpulan hasil akan menjadi 15 baris. Daftar hasil Java dari query ini akan memiliki 15 elemen, semua bertipe Order. Hanya 5 instance Order yang akan dibuat oleh Hibernate, tetapi duplikat dari kumpulan hasil SQL disimpan sebagai referensi duplikat untuk 5 instance ini. Jika Anda tidak memahami kalimat terakhir ini, Anda perlu membaca tentang Java dan perbedaan antara instance di heap Java dan referensi ke instance semacam itu.
(Mengapa left outer join? Jika Anda memiliki pesanan tambahan tanpa item baris, kumpulan hasil akan menjadi 16 baris dengan NULL mengisi sisi kanan, di mana data item baris untuk pesanan lain. Anda menginginkan pesanan meskipun mereka tidak memiliki item baris, bukan? Jika tidak, gunakan inner join fetch di HQL Anda).
Hibernate tidak memfilter referensi duplikat ini secara default. Beberapa orang (bukan Anda) sebenarnya menginginkan ini. Bagaimana Anda bisa menyaringnya?
Seperti ini:
Collection result = new LinkedHashSet( session.create*(...).list() );