Hibernate: Perbedaan antara session.get dan session.load


88

Dari API, saya bisa melihat itu ada hubungannya dengan proxy. Tetapi saya tidak dapat menemukan banyak informasi tentang proxy dan tidak memahami perbedaan antara menelepon session.getdan session.load. Bisakah seseorang menjelaskan atau mengarahkan saya ke halaman referensi?

Terima kasih!!

Jawaban:


117

Dari forum Hibernate :

Ini dari buku Hibernate in Action. Bagus membaca ini ..


Mengambil objek dengan pengidentifikasi Potongan kode Hibernate berikut mengambil objek pengguna dari database:

User user = (User) session.get(User.class, userID);

Metode get () adalah khusus karena pengenal secara unik mengidentifikasi satu instance kelas. Oleh karena itu, aplikasi umum untuk menggunakan pengenal sebagai pegangan yang nyaman untuk objek yang persisten. Pengambilan dengan pengenal bisa menggunakan cache saat mengambil objek, menghindari database yang terkena jika objek sudah di-cache. Hibernate juga menyediakan metode load ():

User user = (User) session.load(User.class, userID);

Metode load () lebih lama; get () ditambahkan ke API Hibernate karena permintaan pengguna. Perbedaannya sepele:

Jika load () tidak dapat menemukan objek dalam cache atau database, pengecualian akan dilemparkan. Metode load () tidak pernah mengembalikan nol. Metode get () mengembalikan null jika objek tidak dapat ditemukan.

Metode load () mungkin mengembalikan proxy alih-alih instance persisten yang nyata. Proksi adalah placeholder yang memicu pemuatan objek nyata saat diakses pertama kali; Di sisi lain, get () tidak pernah mengembalikan proxy. Memilih antara get () dan load () itu mudah: Jika Anda yakin objek persisten ada, dan tidak ada akan dianggap luar biasa, load () adalah pilihan yang baik. Jika Anda tidak yakin ada instance persisten dengan pengenal yang diberikan, gunakan get () dan uji nilai yang dikembalikan untuk melihat apakah nilainya null. Menggunakan load () memiliki implikasi lebih lanjut: Aplikasi dapat mengambil referensi yang valid (proxy) ke instance persisten tanpa menyentuh database untuk mengambil status persistennya. Jadi, load () mungkin tidak memunculkan pengecualian jika tidak menemukan objek persisten dalam cache atau database; pengecualian akan dilempar nanti, saat proxy diakses. Tentu saja, mengambil objek dengan pengenal tidak sefleksibel menggunakan kueri arbitrer.


1
Saya sedang men-debug masalah saat ini di mana session.Get <T> () mengembalikan proxy!
Kent Boogaart

7
Terima kasih banyak! Bagian uang bagi saya adalah: "Jika load () tidak dapat menemukan objek dalam cache atau database, pengecualian dilemparkan. Metode get () mengembalikan null jika objek tidak dapat ditemukan."
Chris

15
JavaDoc untuk Session.get mengatakan: Kembalikan instance persisten dari kelas entitas yang diberikan dengan pengenal yang diberikan, atau null jika tidak ada instance persisten seperti itu. (Jika instance, atau proxy untuk instance, sudah dikaitkan dengan sesi, kembalikan instance atau proxy itu.) Jadi bagian dari buku yang mengatakan: "Di sisi lain, get () tidak pernah mengembalikan proxy." tidak benar.
Vicky

jika Anda menggunakan strategi manajemen transaksi dengan daos Anda, Anda mungkin lebih memilih get (). jika tidak, pemanggil juga harus menjalankan dalam konteks sesi hibernasi terbuka jika load () mengembalikan proxy. misalnya, jika Anda melakukan MVC, pengontrol Anda dapat menjalankan dao.load () dan kemudian membuat pengecualian saat mencoba mengakses objek proxy nanti jika tidak ada sesi yang valid. melakukan dao.get () akan mengembalikan objek sebenarnya ke kontroler terlepas dari sesi (dengan asumsi itu ada)
dev

Masalah yang dijelaskan oleh @Vicky dapat menyebabkan sakit kepala, dan saya tidak melihat keuntungan apa pun darinya. Dalam beberapa kasus, saya juga memerlukan pengenal untuk kueri parametrized lebih lanjut. Tetapi karena proxy objek sudah ada dalam sesi, pengambil pengenal mengembalikan null. Mengapa mereka mengambil proxy alih-alih contoh nyata jika proxy itu ada dalam sesi?
djmj

15

Setidaknya dalam nhibernate, session.Get (id) akan memuat objek dari database, sedangkan session.Load (id) hanya membuat objek proxy untuk itu tanpa meninggalkan server Anda. Bekerja seperti setiap properti lazy-loaded lainnya di POCO Anda (atau POJOs :). Anda kemudian dapat menggunakan proxy ini sebagai referensi ke objek itu sendiri untuk membuat hubungan, dll.

Anggap saja seperti memiliki objek yang hanya menyimpan Id dan yang akan memuat sisanya jika Anda membutuhkannya. Jika Anda hanya menyebarkannya untuk membuat hubungan (seperti FK), id adalah semua yang Anda butuhkan.


jadi Anda ingin mengatakan load (id) pertama-tama akan masuk ke database untuk memeriksa apakah itu id valid atau tidak dan kemudian akan mengembalikan objek proxy dan ketika properti objek ini diakses, itu mengenai database lagi? bukankah itu skenario yang tidak mungkin? dua kueri untuk memuat satu objek?
faisalbhagat

Tidak, load (id) tidak akan memvalidasi id sama sekali sehingga tidak ada perjalanan bolak-balik ke DB. Gunakan hanya jika Anda yakin yakin itu valid.
Jorge Alves

9

session.load () akan selalu mengembalikan "proxy" (istilah Hibernate) tanpa menyentuh database. Dalam Hibernate, proxy adalah objek dengan nilai pengenal yang diberikan, propertinya belum diinisialisasi, hanya terlihat seperti objek palsu sementara. Jika tidak ada baris yang ditemukan, ObjectNotFoundException akan muncul.

session.get () selalu menekan database dan mengembalikan objek sebenarnya, sebuah objek yang mewakili baris database, bukan proxy. Jika tidak ada baris yang ditemukan, itu mengembalikan null.

Performa dengan metode ini juga membuat berbeda. antara dua ...


3

Satu poin ekstra lagi ::

Metode get kelas Sesi Hibernasi mengembalikan null jika objek tidak ditemukan di cache dan juga di database. sedangkan metode load () melontarkan ObjectNotFoundException jika objek tidak ditemukan di cache serta di database tetapi tidak pernah mengembalikan null.


2

Satu konsekuensi tidak langsung dari penggunaan "load" daripada "get" adalah penguncian optimis menggunakan atribut version mungkin tidak berfungsi seperti yang Anda harapkan. Jika pemuatan hanya membuat proxy dan tidak membaca dari database, properti versi tidak dimuat. Versi tersebut hanya akan dimuat ketika / jika Anda nanti merujuk ke properti pada objek, memicu pemilihan. Sementara itu, sesi lain dapat memperbarui objek, dan sesi Anda tidak akan memiliki versi asli yang diperlukan untuk melakukan pemeriksaan kunci optimis - sehingga pembaruan sesi Anda akan menimpa pembaruan sesi lain tanpa peringatan.

Berikut adalah upaya untuk membuat sketsa skenario ini dengan dua sesi yang bekerja dengan objek dengan pengenal yang sama. Versi awal untuk objek di DB adalah 10.

Session 1                  Session 2
---------                  ---------
Load object
Wait a while..   
                           Load object
                           Modify object property
                           [triggers db 'select' -
                            version read as 10]
                           Commit
                           [triggers db update,
                            version modified to 11]
Modify object property
  [triggers db 'select' -
  version read as 11]
Commit
  [triggers db update,
  version modified to 12]

Kami sebenarnya ingin komitmen sesi 1 gagal dengan pengecualian kunci optimis, tetapi akan berhasil di sini.

Menggunakan "get" daripada "load" akan mengatasi masalah tersebut, karena get akan segera mengeluarkan pilihan, dan nomor versi akan dimuat pada waktu yang tepat untuk pemeriksaan kunci yang optimis.


0

Juga kita harus berhati-hati saat menggunakan load karena akan memunculkan eksepsi jika obyek tidak ada. Kita harus menggunakannya hanya jika kita yakin objek itu ada.


0

Penjelasan yang sangat baik ditemukan di http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load ():
Ini akan selalu mengembalikan "proxy" (istilah Hibernate) tanpa mengenai database.
Dalam Hibernate, proxy adalah objek dengan nilai pengenal yang diberikan, propertinya belum diinisialisasi, hanya terlihat seperti objek palsu sementara.
Itu akan selalu mengembalikan objek proxy dengan nilai identitas yang diberikan, bahkan nilai identitas tidak ada dalam database. Namun, ketika Anda mencoba untuk menginisialisasi proxy dengan mengambil propertinya dari database, itu akan mengenai database dengan pernyataan pilih. Jika tidak ada baris yang ditemukan, ObjectNotFoundException akan muncul.
session.get ():
Itu selalu mengenai database (jika tidak ditemukan di cache) dan mengembalikan objek sebenarnya, sebuah objek yang mewakili baris database, bukan proxy.
Jika tidak ada baris yang ditemukan, itu mengembalikan null.


0

load () tidak dapat menemukan objek dari cache atau database, pengecualian dilempar dan metode load () tidak pernah mengembalikan null.

Metode get () mengembalikan null jika objek tidak dapat ditemukan. Metode load () mungkin mengembalikan proxy alih-alih instance persisten nyata get () tidak pernah mengembalikan proxy.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.