Apa properti spring.jpa.open-in-view = true ini di Spring Boot?


121

Saya melihat spring.jpa.open-in-view=trueproperti dalam dokumentasi Spring Boot untuk konfigurasi JPA.

  • Apakah nilai truedefault untuk properti ini jika tidak disediakan sama sekali ?;
  • Apa yang sebenarnya dilakukan ini? Saya tidak menemukan penjelasan yang baik untuk itu;
  • Apakah itu membuat Anda menggunakan, SessionFactorybukan EntityManagerFactory? Jika ya, bagaimana saya bisa mengatakannya untuk mengizinkan saya menggunakan EntityManagerFactory?

Terima kasih!

Jawaban:


52

Properti ini akan mendaftarkan sebuah OpenEntityManagerInViewInterceptor, yang mendaftarkan sebuah EntityManagerke utas saat ini, jadi Anda akan memiliki yang sama EntityManagersampai permintaan web selesai. Ini tidak ada hubungannya dengan Hibernate SessionFactorydll.


Saat ini saya memiliki filter OpenEntityManagerInViewFilter untuk mengontrol EntityManager sampai permintaan web selesai. Pencegat yang Anda maksud "OpenEntityManagerInViewInterceptor" sama dengan "OpenEntityManagerInViewFilter"? Apa perbedaan di antara mereka? Jadi, saya tidak akan memiliki lebih banyak filter ini dalam konteks servlet saya untuk Spring Boot?
Carlos Alberto

1
Pencegat hanya bekerja, ketika Anda menggunakan DispatcherServlet di Spring (karena interceptor adalah mekanisme Spring). Filter dapat dipetakan ke semua servlet yang dikonfigurasi (kami menggunakannya untuk FacesServlet di salah satu aplikasi kami). Jadi jika Anda hanya menggunakan DispatcherServlet, Anda dapat menambahkan properti dan menghapus filter, jika tidak, gunakan filter.
dunni

300

Anti-Pola OSIV

Alih-alih membiarkan lapisan bisnis memutuskan cara terbaik untuk mengambil semua pengaitan yang diperlukan oleh lapisan Tampilan, OSIV (Sesi Terbuka dalam Tampilan) memaksa Konteks Persistensi untuk tetap terbuka sehingga lapisan Tampilan dapat memicu inisialisasi Proxy, seperti yang diilustrasikan dengan diagram berikut.

masukkan deskripsi gambar di sini

  • Itu OpenSessionInViewFilter menyebut openSessionmetode yang mendasari SessionFactorydan memperoleh baru Session.
  • Itu Session terikat ke TransactionSynchronizationManager.
  • Itu OpenSessionInViewFilter menyebut doFilterdari javax.servlet.FilterChainreferensi objek dan permintaan itu diproses lebih lanjut
  • Itu DispatcherServlet disebut, dan rute permintaan HTTP ke mendasari PostController.
  • Itu PostController panggilan PostServiceuntuk mendapatkan daftar Postentitas.
  • Itu PostService membuka transaksi baru, dan HibernateTransactionManagermenggunakan kembali sama Sessionyang dibuka oleh OpenSessionInViewFilter.
  • The PostDAOmenjemput daftar Postentitas tanpa menginisialisasi setiap asosiasi malas.
  • Itu PostService melakukan transaksi yang mendasarinya, tetapi Sessiontidak tertutup karena dibuka secara eksternal.
  • The DispatcherServletdimulai rendering UI, yang, pada gilirannya, menavigasi asosiasi malas dan memicu inisialisasi mereka.
  • The OpenSessionInViewFilterdapat menutup Session, dan koneksi database yang mendasari dilepaskan juga.

Pada pandangan pertama, ini mungkin tidak terlihat seperti hal yang buruk untuk dilakukan, tetapi, setelah Anda melihatnya dari perspektif database, serangkaian kekurangan mulai menjadi lebih jelas.

Lapisan layanan membuka dan menutup transaksi database, tetapi setelah itu, tidak ada transaksi eksplisit yang terjadi. Karena alasan ini, setiap pernyataan tambahan yang dikeluarkan dari fase rendering UI dijalankan dalam mode komit otomatis. Komitmen otomatis memberi tekanan pada server database karena setiap pernyataan harus membuang log transaksi ke disk, sehingga menyebabkan banyak lalu lintas I / O di sisi database. Salah satu pengoptimalan akan menandaiConnection sebagai read-only yang akan memungkinkan server database untuk menghindari penulisan ke log transaksi.

Tidak ada lagi pemisahan masalah karena pernyataan dibuat oleh lapisan layanan dan proses rendering UI. Menulis pengujian integrasi yang menegaskan jumlah pernyataan yang dihasilkan melalui semua lapisan (web, layanan, DAO) saat aplikasi diterapkan di wadah web. Bahkan ketika menggunakan database dalam memori (misalnya HSQLDB) dan web server ringan (misalnya Jetty), pengujian integrasi ini akan lebih lambat untuk dijalankan daripada jika lapisan dipisahkan dan pengujian integrasi back-end menggunakan database, sedangkan pengujian integrasi pengujian integrasi front-end mengejek lapisan layanan sama sekali.

Lapisan UI terbatas untuk menavigasi asosiasi yang pada gilirannya dapat memicu masalah kueri N + 1 . Meskipun Hibernate menawarkan @BatchSizeuntuk mengambil pengaitan dalam kelompok, dan FetchMode.SUBSELECTuntuk mengatasi skenario ini, anotasi memengaruhi rencana pengambilan default, sehingga diterapkan ke setiap kasus penggunaan bisnis. Untuk alasan ini, kueri lapisan akses data jauh lebih cocok karena dapat disesuaikan dengan persyaratan pengambilan data kasus penggunaan saat ini.

Last but not least, koneksi database diadakan sepanjang fase rendering UI yang meningkatkan waktu sewa koneksi dan membatasi throughput transaksi secara keseluruhan karena kemacetan di pool koneksi database. Semakin banyak koneksi ditahan, semakin banyak permintaan bersamaan lainnya yang akan menunggu untuk mendapatkan koneksi dari pool.

Spring Boot dan OSIV

Sayangnya, OSIV (Sesi Terbuka dalam Tampilan) diaktifkan secara default di Spring Boot , dan OSIV benar - benar ide yang buruk dari perspektif kinerja dan skalabilitas .

Jadi, pastikan bahwa di application.propertiesfile konfigurasi, Anda memiliki entri berikut:

spring.jpa.open-in-view=false

Ini akan menonaktifkan OSIV sehingga Anda dapat menangani dengan LazyInitializationExceptioncara yang benar .

Dimulai dengan versi 2.0, Spring Boot mengeluarkan peringatan ketika OSIV diaktifkan secara default, sehingga Anda dapat menemukan masalah ini jauh sebelum itu mempengaruhi sistem produksi.

Untuk detail lebih lanjut tentang OSIV, lihat artikel ini .


14
Ada PERINGATAN yang sedang dicatat saat ini.
Vlad Mihalcea

Apakah ini berlaku untuk Spring secara umum, atau hanya Spring Boot? Dapatkah ini dinonaktifkan melalui kelas @ Configuration-annotated daripada menyetel properti?
Gordon

2
Ini hanya berlaku untuk Spring Boot. Di Spring standar, Anda secara eksplisit memilih kacang apa yang akan digunakan atau apakah Anda menginginkan Filter web, seperti OSIV. Saya tidak tahu apakah Anda dapat menonaktifkannya melalui beberapa anotasi. Saya hanya tahu tentang pengaturan konfigurasi.
Vlad Mihalcea

Ini bukanlah anti-pola. Itu memang memiliki dampak kinerja, terkadang negatif, seringkali cukup netral, dan dalam cara yang positif dalam banyak kasus: jika Anda benar-benar menginginkan hubungan malas untuk memulai, Anda tidak perlu melakukan kueri dalam semua kasus dan dapat menghindarinya saat dibutuhkan dengan menggunakan open-in-view.
ymajoros

5
Menurut Wikipedia, "Anti-pola adalah respons umum terhadap masalah berulang yang biasanya tidak efektif dan berisiko menjadi sangat kontraproduktif". Itulah tepatnya Sesi Terbuka dalam Tampilan.
Vlad Mihalcea
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.