Saya memiliki Order
kelas yang memiliki daftar OrderTransactions
dan saya memetakannya dengan pemetaan Hibernate satu-ke-banyak seperti:
@OneToMany(targetEntity = OrderTransaction.class, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Ini Order
juga memiliki bidang orderStatus
, yang digunakan untuk memfilter dengan Kriteria berikut:
public List<Order> getOrderForProduct(OrderFilter orderFilter) {
Criteria criteria = getHibernateSession()
.createCriteria(Order.class)
.add(Restrictions.in("orderStatus", orderFilter.getStatusesToShow()));
return criteria.list();
}
Ini berhasil dan hasilnya seperti yang diharapkan.
Sekarang inilah pertanyaan saya : Mengapa, ketika saya menyetel jenis pengambilan secara eksplisit ke EAGER
, apakah Order
muncul beberapa kali dalam daftar yang dihasilkan?
@OneToMany(targetEntity = OrderTransaction.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderTransaction> getOrderTransactions() {
return orderTransactions;
}
Bagaimana saya harus mengubah kode Kriteria saya untuk mencapai hasil yang sama dengan pengaturan baru?
Jawaban:
Ini sebenarnya adalah perilaku yang diharapkan jika saya memahami konfigurasi Anda dengan benar.
Anda mendapatkan
Order
contoh yang sama di salah satu hasil, tetapi karena sekarang Anda melakukan penggabungan denganOrderTransaction
, itu harus mengembalikan jumlah hasil yang sama dengan gabungan sql biasa akan mengembalikanJadi sebenarnya itu harus muncul beberapa kali. ini dijelaskan dengan sangat baik oleh penulis (Gavin King) sendiri di sini : Keduanya menjelaskan mengapa, dan bagaimana tetap mendapatkan hasil yang berbeda
Juga disebutkan di FAQ Hibernate :
sumber
Selain apa yang disebutkan oleh Eran, cara lain untuk mendapatkan perilaku yang Anda inginkan, adalah dengan mengatur transformator hasil:
sumber
mencoba
sebagai contoh
}
sumber
Jangan gunakan List dan ArrayList tapi Set dan HashSet.
sumber
Menggunakan Java 8 dan Streams, saya menambahkan metode utilitas saya, pernyataan pengembalian ini:
Stream menghapus duplikat dengan sangat cepat. Saya menggunakan anotasi di kelas Entitas saya seperti ini:
Saya pikir lebih baik di aplikasi saya untuk menggunakan sesi dalam metode di mana saya membutuhkan data dari basis data. Tutup sesi ketika saya selesai. Tentu saja menyetel kelas Entitas saya untuk menggunakan jenis pengambilan yang disewakan. Saya pergi ke refactor.
sumber
Saya memiliki masalah yang sama untuk mengambil 2 koleksi terkait: pengguna memiliki 2 peran (Set) dan 2 makanan (Daftar) dan makanan digandakan.
DISTINCT tidak membantu (kueri DATA-JPA):
Akhirnya saya menemukan 2 solusi:
Solusi akhir:
sumber
Daripada menggunakan peretasan seperti:
Set
dari padaList
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
yang tidak mengubah kueri sql Anda, kami dapat menggunakan (mengutip spesifikasi JPA)
yang memang mengubah kueri sql yang dihasilkan, sehingga memiliki a
DISTINCT
di dalamnya.sumber
Kedengarannya bukan perilaku yang bagus dengan menerapkan gabungan luar dan membawa hasil duplikat. Satu-satunya solusi yang tersisa adalah memfilter hasil kami menggunakan aliran. Terima kasih java8 memberikan cara yang lebih mudah untuk memfilter.
sumber