Untuk penjelasan yang lebih panjang, Anda dapat membaca artikel Open Session In View Anti-Pattern saya . Jika tidak, berikut adalah ringkasan mengapa Anda tidak boleh menggunakan Sesi Terbuka Dalam Tampilan.
Sesi Terbuka Dalam Tampilan mengambil pendekatan yang buruk untuk mengambil data. Alih-alih membiarkan lapisan bisnis memutuskan cara terbaik untuk mengambil semua pengaitan yang dibutuhkan oleh lapisan Tampilan, ini memaksa Konteks Persistensi untuk tetap terbuka sehingga lapisan Tampilan dapat memicu inisialisasi Proxy.
- The
OpenSessionInViewFilter
menyebut openSession
metode yang mendasari SessionFactory
dan memperoleh baru Session
.
- Itu
Session
terikat ke TransactionSynchronizationManager
.
- The
OpenSessionInViewFilter
menyebut doFilter
dari javax.servlet.FilterChain
referensi objek dan permintaan itu diproses lebih lanjut
- The
DispatcherServlet
disebut, dan rute permintaan HTTP ke mendasari PostController
.
- The
PostController
panggilan PostService
untuk mendapatkan daftar Post
entitas.
- The
PostService
membuka transaksi baru, dan HibernateTransactionManager
menggunakan kembali sama Session
yang dibuka oleh OpenSessionInViewFilter
.
- The
PostDAO
menjemput daftar Post
entitas tanpa menginisialisasi setiap asosiasi malas.
- The
PostService
melakukan transaksi yang mendasarinya, tetapi Session
tidak tertutup karena dibuka secara eksternal.
- The
DispatcherServlet
dimulai rendering UI, yang, pada gilirannya, menavigasi asosiasi malas dan memicu inisialisasi mereka.
- The
OpenSessionInViewFilter
dapat 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. Satu optimasi akan menandai Connection
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 harus melalui semua lapisan (web, layanan, DAO), sementara aplikasi diterapkan di wadah web. Bahkan ketika menggunakan database dalam memori (misalnya HSQLDB) dan web server yang ringan (misalnya Jetty), pengujian integrasi ini akan lebih lambat untuk dieksekusi daripada jika lapisan dipisahkan dan pengujian integrasi back-end menggunakan database, sedangkan 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 @BatchSize
untuk mengambil pengaitan dalam kelompok, dan FetchMode.SUBSELECT
untuk mengatasi skenario ini, anotasi memengaruhi rencana pengambilan default, sehingga anotasi tersebut diterapkan ke setiap kasus penggunaan bisnis. Untuk alasan ini, kueri lapisan akses data jauh lebih cocok karena dapat disesuaikan untuk kebutuhan pengambilan data kasus penggunaan saat ini.
Last but not least, koneksi database dapat diadakan selama fase rendering UI (tergantung pada mode rilis koneksi Anda) yang meningkatkan waktu sewa koneksi dan membatasi throughput transaksi secara keseluruhan karena kemacetan pada kumpulan koneksi database. Semakin banyak koneksi ditahan, semakin banyak permintaan bersamaan lainnya yang akan menunggu untuk mendapatkan koneksi dari pool.
Jadi, jika koneksi Anda ditahan terlalu lama, Anda bisa memperoleh / melepaskan beberapa koneksi untuk satu permintaan HTTP, oleh karena itu memberi tekanan pada kumpulan koneksi yang mendasarinya dan membatasi skalabilitas.
Sepatu Musim Semi
Sayangnya, Sesi Terbuka dalam Tampilan diaktifkan secara default di Spring Boot .
Jadi, pastikan bahwa di application.properties
file konfigurasi, Anda memiliki entri berikut:
spring.jpa.open-in-view=false
Ini akan menonaktifkan OSIV, sehingga Anda dapat menangani dengan LazyInitializationException
cara yang benar .