Apa gunanya session.flush () di Hibernate

110

Saat kami memperbarui rekaman, kami dapat menggunakan session.flush()dengan Hibernate. Apa kebutuhannya flush()?

CHANTI
sumber

Jawaban:

138

Pembilasan sesi memaksa Hibernate untuk menyinkronkan status dalam memori Sessiondengan database (yaitu untuk menulis perubahan ke database). Secara default, Hibernate akan menghapus perubahan secara otomatis untuk Anda:

  • sebelum beberapa eksekusi kueri
  • saat transaksi dilakukan

Mengizinkan untuk secara eksplisit membersihkan Sessionmemberikan kontrol yang lebih baik yang mungkin diperlukan dalam beberapa situasi (untuk mendapatkan ID yang ditetapkan, untuk mengontrol ukuran Sesi, ...).

Pascal Thivent
sumber
8
Perhatikan bahwa jawaban ini menjelaskan perilaku DEFAULT Hibernate: perilaku pembilasan dapat diubah melalui pengaturan Mode Pembersihan. Detail ada di docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (versi 3.5).
SteveT
1
Saya menemukan dokumen di mana dikatakan persis apa yang Anda katakan tetapi saya memiliki pertanyaan bahwa apa yang akan menjadi prioritas berarti misalkan 1) Saya memiliki kelas di mana saya menyimpan objek menggunakan kode id = session.save(obj);dan transaksi dilakukan di baris berikutnya tetapi obj tidak diselamatkan ke DB, Mengapa? 2) Saya menyimpan obj menggunakan session.save(obj);dengan komit dan saat kembali saya digunakan return obj.getprimaryID();Dalam hal ini obj disimpan ke DB. Jadi mengapa perilaku ini terjadi?
Amogh
74

Seperti yang dikatakan dengan benar dalam jawaban di atas, dengan menelepon flush() kami memaksa hibernate untuk menjalankan perintah SQL pada Database. Tapi pahamilah bahwa perubahan belum "dilakukan". Jadi setelah melakukan flush dan sebelum melakukan commit, jika Anda mengakses DB secara langsung (katakanlah dari SQL prompt) dan memeriksa baris yang dimodifikasi, Anda TIDAK akan melihat perubahannya.

Ini sama dengan membuka 2 sesi perintah SQL. Dan perubahan yang dilakukan dalam 1 sesi tidak terlihat oleh orang lain hingga dilakukan.

Kaushik Lele
sumber
12
Nah - perubahannya bisa sedikit terlihat. Misalnya, baris yang tidak terikat dapat membuat kunci pada baris yang disisipkan tetapi tidak terikat dan menunda baris yang sama untuk disisipkan oleh sesi lain sampai transaksi dilakukan atau dibatalkan. Jadi tidak sepenuhnya tidak terlihat.
rghome
2
Saya telah menjelajahi seluruh web dan inilah jawaban yang akhirnya membuat saya mengerti. Terima kasih.
Siddhartha
apa gunanya menempatkan .flush () di loop for kemudian jika commit () melakukan flush di akhir?
Eildosa
@Kik ​​Lele Apa gunanya flush () jika data tidak terlihat setelah flush? Dapatkah Anda menjelaskan beberapa kasus penggunaan yang lebih baik yang berguna?
java_geek
28

Saya hanya tahu bahwa ketika kami memanggil session.flush()pernyataan kami dieksekusi dalam database tetapi tidak berkomitmen.

Misalkan kita tidak memanggil flush()metode pada objek sesi dan jika kita memanggil metode komit maka secara internal akan melakukan pekerjaan mengeksekusi pernyataan pada database dan kemudian melakukan.

commit=flush+commit (dalam hal fungsionalitas)

Jadi, saya menyimpulkan bahwa ketika kita memanggil metode flush () pada objek Sesi, maka itu tidak mendapatkan komit tetapi mengenai database dan mengeksekusi kueri dan mendapatkan rollback juga.

Untuk melakukan kita menggunakan commit () pada objek Transaction.

Shoaib Chikate
sumber
Bisakah Anda memberikan beberapa detail tentang apa yang dibutuhkan untuk flush?
java_geek
14

Pembilasan Sesi membuat data yang saat ini ada dalam sesi disinkronkan dengan apa yang ada di database.

Lebih lanjut di situs web Hibernate:

flush()berguna, karena sama sekali tidak ada jaminan tentang kapan Sesi mengeksekusi panggilan JDBC, hanya urutan eksekusi panggilan tersebut - kecuali yang Anda gunakan flush().

miku
sumber
Dapatkah Anda memberikan skenario ketika pengguna harus mengkhawatirkan urutannya? Penggunaan hibernate adalah untuk membuat hal-hal terkait DB menjadi transparan bagi pengguna. Saat kita melakukan "commit", flushing terjadi secara otomatis. Bagaimana skenario di mana Anda akan melakukan flush tetapi tidak melakukan?
Kaushik Lele
1
@KaushikLele Anda dapat merujuk ke pertanyaan ini stackoverflow.com/questions/37382872/…
GMsoF
10

Anda mungkin menggunakan flushuntuk memaksa batasan validasi direalisasikan dan dideteksi di tempat yang diketahui daripada saat transaksi dilakukan. Mungkin yang commitdipanggil secara implisit oleh beberapa logika kerangka kerja, melalui logika deklaratif, wadah, atau oleh template. Dalam kasus ini, pengecualian apa pun yang dilemparkan mungkin sulit ditangkap dan ditangani (bisa jadi terlalu tinggi dalam kode).

Misalnya, jika Anda save()memiliki objek EmailAddress baru, yang memiliki batasan unik pada alamat, Anda tidak akan mendapatkan kesalahan hingga Anda melakukannya.

Memanggil flush()memaksa baris untuk disisipkan, mengeluarkan Exception jika ada duplikat.

Namun, Anda harus memutar kembali sesi setelah pengecualian.

rghome
sumber
4

Saya hanya ingin menggabungkan semua jawaban yang diberikan di atas dan juga menghubungkan metode Flush () dengan Session.save () untuk memberikan lebih banyak perhatian

Hibernate save () dapat digunakan untuk menyimpan entitas ke database. Kita dapat memanggil metode ini di luar transaksi, itulah mengapa saya tidak suka metode ini untuk menyimpan data. Jika kita menggunakan ini tanpa transaksi dan kita memiliki cascading antar entitas, maka hanya entitas utama yang disimpan kecuali kita membilas sesi.

flush (): Memaksa sesi untuk dibilas. Ini digunakan untuk menyinkronkan data sesi dengan database.

Saat Anda memanggil session.flush (), pernyataan dijalankan dalam database tetapi tidak akan dikomit. Jika Anda tidak memanggil session.flush () dan jika Anda memanggil session.commit (), metode commit () secara internal akan mengeksekusi pernyataan dan melakukan.

Jadi komit () = flush + komit. Jadi session.flush () hanya mengeksekusi pernyataan dalam database (tapi tidak melakukan) dan pernyataan TIDAK DI DALAM MEMORI lagi. Itu hanya memaksa sesi untuk memudar.

Beberapa poin penting:

Kita harus menghindari penyimpanan di luar batas transaksi, jika tidak entitas yang dipetakan tidak akan disimpan menyebabkan ketidakkonsistenan data. Sangat normal untuk melupakan sesi flushing karena tidak ada pengecualian atau peringatan apa pun. Secara default, Hibernate akan menghapus perubahan secara otomatis untuk Anda: sebelum beberapa eksekusi kueri saat transaksi dilakukan Mengizinkan untuk secara eksplisit menghapus Sesi memberikan kontrol yang lebih baik yang mungkin diperlukan dalam beberapa keadaan (untuk mendapatkan ID yang ditetapkan, untuk mengontrol ukuran Sesi )

Sundar Gsv
sumber
3

The flush() Metode menyebabkan Hibernate untuk flush sesi. Anda dapat mengkonfigurasi Hibernate untuk menggunakan mode pembilasan untuk sesi dengan menggunakan setFlushMode()metode. Untuk mendapatkan mode flush untuk sesi saat ini, Anda dapat menggunakan getFlushMode()metode. Untuk mengecek, apakah session itu kotor, Anda bisa menggunakan isDirty()metode. Secara default, Hibernate mengelola pembilasan sesi.

Seperti yang tertera dalam dokumentasi:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

Pembilasan

Pembilasan adalah proses sinkronisasi keadaan konteks persistensi dengan database yang mendasarinya. The EntityManagerdan Hibernate Sessionmengekspos serangkaian metode, di mana pengembang aplikasi dapat mengubah status persisten dari suatu entitas.

Konteks persistensi bertindak sebagai cache tulis di belakang transaksional, mengantri setiap perubahan status entitas. Seperti cache di belakang penulisan, perubahan pertama kali diterapkan dalam memori dan disinkronkan dengan database selama waktu flush. Operasi flush mengambil setiap perubahan status entitas dan menerjemahkannya menjadi pernyataan INSERT, UPDATEatau DELETE.

Strategi pembilasan diberikan oleh flushMode dari Sesi Hibernasi yang sedang berjalan. Meskipun JPA hanya mendefinisikan dua strategi pembilasan ( AUTOdan COMMIT), Hibernate memiliki spektrum jenis pembilasan yang jauh lebih luas:

  • ALWAYS: Mengosongkan Sesi sebelum setiap kueri;
  • AUTO: Ini adalah mode default dan menghapus Sesi hanya jika perlu;
  • COMMIT: Sesi mencoba untuk menunda flush hingga Transaksi saat ini dilakukan, meskipun mungkin juga flush sebelum waktunya;
  • MANUAL: Sesi pembilasan didelegasikan ke aplikasi, yang harus memanggil Session.flush()secara eksplisit untuk menerapkan perubahan konteks persistensi.

Secara default, Hibernate menggunakan AUTOmode flush yang memicu flush dalam keadaan berikut:

  • sebelum melakukan Transaksi;
  • sebelum mengeksekusi query JPQL / HQL yang tumpang tindih dengan antrian tindakan entitas;
  • sebelum menjalankan kueri SQL asli apa pun yang tidak memiliki sinkronisasi terdaftar.

sumber
1

Menelepon EntityManager#flushmemang memiliki efek samping . Ini mudah digunakan untuk tipe entitas dengan nilai ID yang dihasilkan (nilai urutan): ID semacam itu hanya tersedia setelah sinkronisasi dengan lapisan persistensi yang mendasarinya. Jika ID ini diperlukan sebelum transaksi saat ini berakhir (untuk tujuan logging misalnya), diperlukan pembersihan sesi.

johanwannheden
sumber
0

Dengan metode ini Anda membangkitkan proses penyiraman. Proses ini menyinkronkan status database Anda dengan status sesi Anda dengan mendeteksi perubahan status dan menjalankan pernyataan SQL masing-masing.

lennoxGER
sumber