Saya seorang pemula untuk Java Persistence API dan Hibernate.
Apa perbedaan antara FetchType.LAZY
dan FetchType.EAGER
di Java Persistence API?
Saya seorang pemula untuk Java Persistence API dan Hibernate.
Apa perbedaan antara FetchType.LAZY
dan FetchType.EAGER
di Java Persistence API?
Jawaban:
Terkadang Anda memiliki dua entitas dan ada hubungan di antara mereka. Misalnya, Anda mungkin memiliki entitas yang dipanggil
University
dan entitas lain yang dipanggilStudent
dan Universitas mungkin memiliki banyak Mahasiswa:Entitas Universitas mungkin memiliki beberapa properti dasar seperti id, nama, alamat, dll. Serta properti koleksi yang disebut siswa yang mengembalikan daftar siswa untuk universitas tertentu:
Sekarang ketika Anda memuat Universitas dari database, JPA memuat bidang id, nama, dan alamatnya untuk Anda. Tetapi Anda memiliki dua opsi untuk bagaimana siswa harus dimuat:
getStudents()
.Ketika sebuah universitas memiliki banyak siswa, tidaklah efisien untuk memuat semua mahasiswanya bersama-sama dengannya, terutama ketika mereka tidak dibutuhkan dan dalam kasus-kasus serupa Anda dapat menyatakan bahwa Anda ingin siswa dimuat ketika mereka sebenarnya dibutuhkan. Ini disebut pemuatan malas.
Berikut ini contoh, di mana
students
ditandai secara eksplisit untuk dimuat dengan penuh semangat:Dan inilah contoh di mana
students
secara eksplisit ditandai untuk dimuat dengan malas:sumber
getStudents()
), Tetapi kadang-kadang ini tidak mungkin, karena pada saat metode ini dipanggil, sesi sudah ditutup dan entitas terlepas. Demikian pula, kadang-kadang kita memiliki arsitektur klien / server (misalnya klien Swing / server JEE) dan entitas / DTO ditransfer melalui kawat ke klien dan sekali lagi paling sering dalam skenario ini pemuatan malas tidak akan berfungsi karena cara entitas diserialkan melalui kabel.getStudents()
metode untuk pertama kalinya, apakah hasilnya di-cache? sehingga saya dapat mengakses hasil tersebut lebih cepat di waktu berikutnya?Pada dasarnya,
sumber
EAGER
memuat koleksi berarti bahwa mereka diambil sepenuhnya pada saat orang tua mereka diambil. Jadi jika sudahCourse
dan sudahList<Student>
, semua siswa diambil dari database pada saatCourse
diambil.LAZY
di sisi lain berarti bahwa kontenList
diambil hanya ketika Anda mencoba mengaksesnya. Misalnya dengan meneleponcourse.getStudents().iterator()
. Memanggil metode akses apa pun padaList
akan memulai panggilan ke database untuk mengambil elemen. Ini diimplementasikan dengan membuat Proxy di sekitarList
(atauSet
). Jadi untuk koleksi malas Anda, jenis betonnya bukanArrayList
danHashSet
, tapiPersistentSet
danPersistentList
(atauPersistentBag
)sumber
course.getStudents()
, ia meluncurkan query SQL (melihatnya di konsol). Dalam jenis pengambilan Malas juga, hal yang sama terjadi. Jadi, apa bedanya ??fetchtype = LAZY
default bahkan jika mencoba untuk mendapatkan koleksi dengan pengambil hibernete melempar kesalahan mengatakan saya itu tidak dapat mengevaluasiSaya dapat mempertimbangkan kinerja dan pemanfaatan memori. Satu perbedaan besar adalah bahwa strategi pengambilan EAGER memungkinkan untuk menggunakan objek data yang diambil tanpa sesi. Mengapa?
Semua data diambil saat ingin menandai data di objek saat sesi terhubung. Namun, dalam kasus strategi pemuatan malas, pemuatan malas objek yang ditandai tidak mengambil data jika sesi terputus (setelah
session.close()
pernyataan). Semua itu bisa dilakukan dengan hibernate proxy. Strategi yang bersemangat memungkinkan data tetap tersedia setelah sesi penutupan.sumber
Sesuai pengetahuan saya, kedua jenis pengambilan tergantung kebutuhan Anda.
FetchType.LAZY
sesuai permintaan (yaitu saat kami membutuhkan data).FetchType.EAGER
langsung (yaitu sebelum persyaratan kami datang kami tidak perlu mengambil catatan)sumber
Secara default, untuk semua objek koleksi dan peta, aturan pengambilannya adalah
FetchType.LAZY
dan untuk kasus lain, ia mengikutiFetchType.EAGER
kebijakan.Singkatnya,
@OneToMany
dan@ManyToMany
relasi tidak mengambil objek terkait (pengumpulan dan peta) secara implisit tetapi operasi pengambilan mengalir melalui bidang@OneToOne
dan objek@ManyToOne
.(courtesy: - objectdbcom)
sumber
Keduanya
FetchType.LAZY
danFetchType.EAGER
digunakan untuk menentukan rencana pengambilan default .Sayangnya, Anda hanya dapat mengganti rencana pengambilan default untuk pengambilan LAZY. Pengambilan EAGER kurang fleksibel dan dapat menyebabkan banyak masalah kinerja .
Saran saya adalah untuk menahan keinginan membuat asosiasi Anda LEBIH BAIK karena mengambil adalah tanggung jawab waktu permintaan. Jadi semua pertanyaan Anda harus menggunakan arahan ambil untuk hanya mengambil apa yang diperlukan untuk kasus bisnis saat ini.
sumber
Dari Javadoc :
Misalnya, bersemangat lebih proaktif daripada malas. Malas hanya terjadi pada penggunaan pertama (jika penyedia mengambil petunjuk), sedangkan dengan hal-hal yang ingin (mungkin) mendapatkan pre-fetched.
sumber
The
Lazy
Fetch jenis adalah secara default dipilih oleh Hibernate kecuali Anda secara eksplisit menandaiEager
Ambil jenis. Agar lebih akurat dan ringkas, perbedaan dapat dinyatakan sebagai berikut.FetchType.LAZY
= Ini tidak memuat hubungan kecuali Anda memintanya melalui metode pengambil.FetchType.EAGER
= Ini memuat semua hubungan.Pro dan Kontra dari dua jenis pengambilan ini.
Lazy initialization
meningkatkan kinerja dengan menghindari perhitungan yang tidak perlu dan mengurangi kebutuhan memori.Eager initialization
membutuhkan lebih banyak konsumsi memori dan kecepatan pemrosesan lambat.Karena itu, tergantung pada situasi salah satu inisialisasi ini dapat digunakan.
sumber
getMember
dipanggil yang persis sesuai dengan pola nama anggota?Book.java
Subject.java
HibernateUtil.java
Main.java
Periksa metode ambil () dari Main.java. Ketika kita mendapatkan Subjek, maka daftar koleksi Buku , yang dijelaskan dengan
@OneToMany
, akan dimuat dengan malas. Tetapi, di sisi lain, Buku-buku yang berhubungan dengan asosiasi subjek koleksi , dijelaskan dengan@ManyToOne
, memuat lebih banyak (oleh[default][1]
untuk@ManyToOne
,fetchType=EAGER
). Kita dapat mengubah perilaku dengan menempatkan fetchType.EAGER di@OneToMany
Subject.java atau fetchType.LAZY di@ManyToOne
dalam Books.java.sumber
Sumber
sumber
Saya ingin menambahkan catatan ini pada apa yang dikatakan "Kyung Hwan Min" di atas.
Misalkan Anda menggunakan Spring Rest dengan arsitek sederhana ini:
Dan Anda ingin mengembalikan beberapa data ke front-end, jika Anda menggunakan
FetchType.LAZY
, Anda akan mendapatkan pengecualian setelah Anda mengembalikan data ke metode pengontrol karena sesi ditutup di Layanan sehinggaJSON Mapper Object
tidak bisa mendapatkan data.Ada tiga opsi umum untuk mengatasi masalah ini, tergantung pada desain, kinerja, dan pengembang:
FetchType.EAGER
, Sehingga sesi akan tetap hidup pada metode controller.FetchType.LAZY
metode konverter untuk mentransfer data dariEntity
ke objek data lainDTO
dan mengirimkannya ke pengontrol, sehingga tidak ada pengecualian jika sesi ditutup.sumber
Hai, saya telah melampirkan 2 foto untuk membantu Anda memahami hal ini.
sumber
@ drop-shadow jika Anda menggunakan Hibernate, Anda dapat memanggil
Hibernate.initialize()
ketika Anda memanggilgetStudents()
metode:sumber
LAZY: Itu mengambil entitas anak dengan malas, yaitu pada saat mengambil entitas induk, ia hanya mengambil proxy (dibuat oleh cglib atau utilitas lain) dari entitas anak dan ketika Anda mengakses properti entitas anak maka sebenarnya diambil oleh hibernate.
EAGER: itu mengambil entitas anak bersama dengan orang tua.
Untuk pemahaman yang lebih baik, buka dokumentasi Jboss atau Anda dapat menggunakan
hibernate.show_sql=true
untuk aplikasi Anda dan memeriksa pertanyaan yang dikeluarkan oleh hibernate.sumber