Jenis pengambilan default untuk satu-ke-satu, banyak-ke-satu dan satu-ke-banyak dalam Hibernate

103

Apa jenis pengambilan default dalam pemetaan hibernasi?

Yang saya ketahui setelah menjelajah adalah:

  • untuk satu lawan satu, hal itu sangat menarik .
  • untuk satu-ke-banyak itu malas .

Tapi setelah mengujinya di Eclipse, semuanya bersemangat.

Apakah ini tergantung pada apakah saya menggunakan JPA atau Hibernate?

Richa
sumber
1
Jika Anda masih terlibat dalam topik JPA - Saya memperbarui pertanyaan Anda dengan jawaban baru, karena yang lama sudah usang untuk versi Hibernate saat ini.
Alexander Rühl

Jawaban:

193

Itu tergantung pada apakah Anda menggunakan JPA atau Hibernate.

Dari spesifikasi JPA 2.0 , defaultnya adalah:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

Dan saat hibernasi, semuanya Malas

MEMPERBARUI:

Versi terbaru dari Hibernate sejalan dengan default JPA di atas.

Ashish Agarwal
sumber
11
"Dan saat hibernate, all is Lazy" rupanya sudah berubah di versi terbaru. Silakan lihat jawaban Alexander Rühl di bawah .
Dinei
1
Hibernate adalah salah satu implementasi JPA, jadi setelah Anda menggunakan Hibernate, Anda menggunakan JPA :)
xenteros
Ini adalah pertanyaan yang populer. @Ashish Agarwal Bisakah Anda memperbarui baris terakhir jawaban Anda. Di Hibernate, ini bukan Lazy untuk semua sekarang.
Saurabh Tiwari
Memperbarui postingan terkait dengan perilaku Hibernasi terbaru.
M Anouti
Ada pembaruan, mengklaim bahwa eager adalah tipe pengambilan default untuk setiap pemetaan, yang dibantah oleh bab 11.3 di dokumentasi Hibernate 5.x saat ini dan 6.x baru, jadi saya membatalkan pengeditan. Selain itu, tidak disarankan untuk tidak memiliki keinginan otomatis, karena ini berarti mungkin memilih seluruh database saat mengambil satu objek.
Alexander Rühl
51

Saya tahu jawabannya benar pada saat mengajukan pertanyaan - tetapi karena orang-orang (seperti saya saat ini) masih kebetulan menemukan mereka bertanya-tanya mengapa WildFly 10 mereka berperilaku berbeda, saya ingin memberikan pembaruan untuk Hibernate 5 saat ini versi .x:

Dalam Panduan Pengguna Hibernate 5.2 disebutkan di bab 11.2. Menerapkan strategi pengambilan :

Rekomendasi Hibernate adalah menandai secara statis semua asosiasi sebagai malas dan menggunakan strategi pengambilan dinamis untuk keinginan. Sayangnya, hal ini bertentangan dengan spesifikasi JPA yang menetapkan bahwa semua pengaitan one-to-one dan many-to-one harus diambil secara default . Hibernate, sebagai penyedia JPA, menghormati default itu.

Jadi Hibernate juga berperilaku seperti Ashish Agarwal yang disebutkan di atas untuk JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(lihat Spesifikasi JPA 2.1 )

Alexander Rühl
sumber
Dan bagaimana jika kita menggunakan hibernate asli daripada JPA impl, apakah itu bertindak dengan cara yang sama?
jMounir
@jMounir: Saya belum mencobanya, tetapi karena Hibernate menyatakan bahwa ia berperilaku seperti yang didefinisikan dalam JPA, saya tidak mengerti mengapa hal itu akan berbeda saat menggunakan Hibernate untuk dirinya sendiri. Dalam kedua kasus, seseorang dapat mengganti strategi default.
Alexander Rühl
15

Untuk menjawab pertanyaan Anda, Hibernate merupakan implementasi dari standar JPA. Hibernate memiliki kebiasaan operasinya sendiri, tetapi sesuai dengan dokumen Hibernate

Secara default, Hibernate menggunakan pengambilan pilih lambat untuk koleksi dan pengambilan proxy lambat untuk asosiasi bernilai tunggal. Default ini masuk akal untuk sebagian besar pengaitan di sebagian besar aplikasi.

Jadi Hibernate akan selalu memuat objek apa pun menggunakan strategi pengambilan lambat, apa pun jenis hubungan yang telah Anda nyatakan. Ini akan menggunakan proxy malas (yang harus tidak diinisialisasi tetapi tidak null) untuk satu objek dalam hubungan satu-ke-satu atau banyak-ke-satu, dan koleksi nol yang akan terhidrasi dengan nilai ketika Anda mencoba mengaksesnya .

Harus dipahami bahwa Hibernate hanya akan mencoba untuk mengisi objek-objek ini dengan nilai-nilai ketika Anda mencoba mengakses objek tersebut, kecuali Anda tentukan fetchType.EAGER.

JamesENL
sumber
0

Untuk asosiasi bernilai tunggal, ie-One-to-One dan Many-to-One: -
Default Lazy = proxy
Proxy lazy loading : - Ini berarti objek proxy dari entitas terkait Anda dimuat. Ini berarti bahwa hanya id yang menghubungkan dua entitas yang dimuat untuk objek proxy dari entitas terkait.
Misalnya: A dan B adalah dua entitas dengan asosiasi Banyak ke satu. yaitu: Mungkin ada beberapa A untuk setiap B. Setiap objek A akan berisi referensi dari B.
`

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
Relasi A akan berisi kolom (bantuan, tawaran, ... kolom lain dari entitas A).
Relasi B akan berisi kolom (bid, ... kolom lain dari entitas B)

Proksi menyiratkan ketika A diambil, hanya id yang diambil untuk B dan disimpan ke dalam objek proxy B yang hanya berisi id. Objek proxy B adalah objek kelas proxy yang merupakan subkelas B dengan hanya bidang minimal. Karena tawaran sudah menjadi bagian dari relasi A, tidak perlu mengaktifkan kueri untuk mendapatkan tawaran dari relasi B. Atribut lain dari entitas B dimuat secara malas hanya ketika bidang selain tawaran diakses.

Untuk Koleksi, ie-Many-to-Many dan One-to-Many: -
Default Lazy = true


Harap dicatat juga bahwa strategi fetch (pilih, gabung dll) dapat menimpa malas. yaitu: Jika lazy = 'true' dan fetch = 'join', pengambilan A juga akan mengambil B atau B (Jika ada koleksi). Anda bisa mendapatkan alasannya jika Anda memikirkannya.
Pengambilan default untuk satu asosiasi bernilai adalah "bergabung".
Pengambilan default untuk koleksi adalah "pilih". Harap verifikasi dua baris terakhir. Saya telah menyimpulkannya secara logis.

Jijo Mathew
sumber