Buka Sesi Dalam Tampilan di Boot Spring: The Phantom Menace

Setiap orang di sini benar, masing-masing dengan caranya sendiri, dan karena itu setiap orang di sini salah.
"The Tale of the Three" (A. dan B. Strugatsky)

Jika Anda menggunakan Spring Data JPA, kemudian setelah memperbarui ke Spring Boot 2, saat Anda memulai aplikasi, Anda mungkin melihat peringatan baru di log:


spring.jpa.open-in-view diaktifkan secara default. Oleh karena itu, permintaan basis data dapat dilakukan selama rendering tampilan. Konfigurasikan spring.jpa.open-in-view secara eksplisit untuk menonaktifkan peringatan ini.

Dalam artikel ini saya akan mencoba menjelaskan apa artinya, siapa yang harus disalahkan dan apa yang harus dilakukan.


Untuk memunculkan aplikasi lengkap pada Boot Musim Semi, hanya diperlukan satu penjelasan @SpringBootApplication . Untuk memungkinkan ini, kerangka kerja menggunakan sejumlah besar konfigurasi otomatis dan pengaturan default. Selain itu, untuk bekerja di luar kotak, pengembang Spring Boot harus memilih beberapa konsep pengembangan aplikasi dari beberapa opsi alternatif untuk masing-masing, sehingga pengguna tidak perlu memilihnya secara eksplisit. Di satu sisi, ini bagus untuk memulai cepat dan pengembangan mudah, tetapi di sisi lain, setelah beberapa saat mungkin ternyata beberapa konsep / paradigma / pengaturan default tidak cocok untuk proyek, dan banyak pekerjaan yang harus dilakukan untuk mengabaikannya. Salah satu konsep tersebut adalah mode Open Session In View (OSIV) , yang disertakan secara default di Spring Boot.


Dalam mode ini, sesi Hibernasi tetap terbuka sepanjang waktu permintaan HTTP diproses, termasuk tahap pembuatan Lihat (sumber JSON atau halaman HTML). Ini memungkinkan untuk memuat data dengan malas di lapisan presentasi setelah melakukan transaksi di lapisan logika bisnis. Sebagai contoh, kami meminta entitas Article dari database. Artikel harus ditampilkan bersama dengan komentar. OSIV memungkinkan Anda cukup memanggil metode entitas getComments() saat merender HTML, dan komentar akan dimuat dalam permintaan terpisah. Ketika mode OSIV dinonaktifkan, kita akan mendapatkan LazyInitializationException , karena sesi sudah ditutup dan entitas Article tidak lagi dikelola oleh Hibernate. Sebagian besar pengembang Hibernate mengalami LazyInitializationException ; OSIV memungkinkan Anda untuk menghindarinya dengan memuat data seperlunya pada setiap tahap pemrosesan permintaan HTTP.


OSIV di Spring Boot diimplementasikan menggunakan OpenEntityManagerInViewInterceptor permintaan web OpenEntityManagerInViewInterceptor . Tidak seperti Spring murni, ini diaktifkan secara default.


OSIV dianggap antipattern. Yang terbaik dari semuanya, sisi berbahaya dari artikelnya dijelaskan oleh Vlad Mihalcea, salah satu pengembang Hibernate: Sesi Terbuka Dalam Pandangan Anti-Pola . Poin-poin penting:


  • Permintaan basis data tanpa transaksi berfungsi dalam mode komit otomatis, memuatnya dengan berat.
  • Tidak ada pemisahan tanggung jawab, lapisan aplikasi apa pun dapat menghasilkan kueri SQL, yang membuat pengujian menjadi sulit.
  • Ada masalah n +1 ketika setiap koleksi terkait dengan entitas dimuat dalam permintaan terpisah.
  • Koneksi yang lama ke database sekali lagi menambah beban di dalamnya dan mengurangi throughput.

Ini adalah masalah yang cukup tidak menyenangkan dari mode OSIV dan, tampaknya, argumen kuat untuk tidak menggunakannya. Namun, dalam permintaan untuk menonaktifkannya secara default , pengembang Spring Boot juga membuat alasan bagus mengapa OSIV harus diaktifkan untuk proyek-proyek baru:


  • Kompatibilitas mundur. Aplikasi yang ada saat meningkatkan ke Spring Boot 2 mungkin mengalami kesalahan dan bug karena OSIV dinonaktifkan. Untuk menghindari ini, Anda hanya perlu mengatur nilai tunggal spring.jpa.open-in-view , tetapi ini juga membuatnya sulit untuk beralih ke versi baru.
  • Kemudahan penggunaan untuk pemula dan awal yang cepat penting untuk Spring Boot. Jika OSIV dinonaktifkan, mungkin tidak jelas bagi pemula mengapa hal yang diharapkan secara intuitif seperti menerima koleksi elemen terkait saat mengakses metode entitas tidak berfungsi. Sebagai gantinya, pengguna akan menerima LazyInitializationException , ini akan memperlambat jalannya ke aplikasi yang sedang berjalan.
  • OSIV memungkinkan Anda untuk meningkatkan kesederhanaan kode, kegunaan, dan kecepatan pengembangan.
  • Sulit untuk menemukan contoh sederhana tentang bagaimana suatu aplikasi harus dibangun tanpa OSIV.
  • Tanpa OSIV, lapisan logika bisnis perlu tahu bagaimana data akan disajikan di UI, yaitu, DTO apa yang dibutuhkan atau data terkait apa yang harus dimuat bersama dengan entitas root. Lagi-lagi ini tidak ada pembagian tanggung jawab.

Jadi, kita bisa membedakan dua pandangan tentang masalah ini. Dari sudut pandang arsitek basis data (DBA), Open Session In View tentu saja tidak dapat diterima, karena interaksi aplikasi dengan database tidak diatur secara optimal dan menghasilkan peningkatan beban. Tetapi kami sering menggunakan solusi yang kurang optimal untuk kecepatan, kemudahan pengembangan dan kemudahan alat pembelajaran - kami menulis dalam bahasa yang dikelola, kami menggunakan format data teks untuk interaksi jaringan dan sebagainya. Dari posisi pengembang kerangka kerja, untuk menyederhanakan pengembangan dan mulai cepat pemula, OSIV memungkinkan Anda untuk mengurangi beban kognitif, sejumlah konsep yang diperlukan untuk mulai mengembangkan aplikasi. Jika pengembang memilih JPA, dia sudah menyetujui beberapa penurunan kinerja dengan imbalan kenyamanan pengembangan. JPA membantu berteman dengan objek dan model data relasional. Ketika bekerja dalam gaya objek untuk mendapatkan elemen terkait, kita cukup beralih ke metode entitas (bahkan jika dalam lapisan presentasi), itu sederhana, logis dan secara intuitif diharapkan, meskipun kesederhanaan ini menipu.


Ada banyak contoh dan tutorial untuk bekerja dalam mode Sesi Terbuka Dalam mode Tampilan, arsitektur secara keseluruhan jelas: lapisan layanan meminta entitas JPA, lapisan presentasi secara bersambung di JSON secara langsung, melalui DTO perantara, atau menggunakan data darinya untuk membuat halaman HTML.


Yang kurang jelas adalah bagaimana bekerja tanpa OSIV. Salah satu pengembang Spring dalam permintaan tersebut mengeluh tentang hal ini, mereka mengatakan banyak teriakan tentang antipattern, tetapi tidak ada contoh sederhana tentang bagaimana hidup tanpanya. Dalam varian ini, entitas hanya dapat digunakan untuk menulis, dan untuk membaca - beberapa DTO, terpisah untuk setiap set data di UI, yang dipetakan langsung dari database. Atau kueri SQL khusus yang menggambarkan gabungan dari koleksi terkait yang diperlukan untuk kueri web tertentu. Artinya, lebih banyak boilerplate dan deskripsi kebutuhan UI di lapisan logika bisnis. Dengan OSIV dinonaktifkan, abstraksi JPA mulai mengalir, aplikasi menjelaskan lebih detail teknis berinteraksi dengan database.


Dengan demikian, pengembangan dengan OSIV lebih sederhana. Tetapi masalahnya adalah jika di masa depan Anda ingin meninggalkannya, Anda harus mengulang banyak hal, konsep bekerja dengan database dalam proyek dengan menetapkan satu properti tidak dapat diubah. Anda mungkin perlu mengulang seluruh arsitektur aplikasi. Namun, mengabaikan OSIV mungkin merupakan pengoptimalan prematur, yang akan memperlambat kecepatan pengembangan, yang mungkin sangat penting untuk startup, misalnya. Anda dapat menggunakan OSIV dan mengoptimalkan kueri basis data hanya di tempat paling lambat. Misalnya, kueri koleksi entitas paling menderita dari masalah n +1, ketika setiap entitas menarik beberapa kueri dari koleksi terkait.


Jadi, jika Anda ingin melakukannya dengan benar, Anda perlu mengembangkan tanpa OSIV. Tetapi jika kecepatan pengembangan dan kesederhanaan kode penting, Anda dapat menggunakan mode ini, mengundurkan diri ke beberapa kehilangan kinerja.


Masalah utamanya adalah masalah kinerja ini tidak berubah menjadi hutang teknis yang besar setelah beberapa tahun. Sangat berbahaya ketika pengembang tidak curiga bahwa utang ini menumpuk di dalamnya, karena Spring Boot diam-diam memilih konsep Open Session In View untuk mereka. Oleh karena itu, sangat baik bahwa, sebagai hasil dari permintaan yang disebutkan di atas, diputuskan untuk menampilkan di log peringatan tentang mode yang digunakan, yang saya kutip di awal artikel.


Saya harap peringatan dan artikel tentang dia ini akan membantu pengembang membuat keputusan yang lebih tepat - apakah akan menggunakan konsep Open Session In View dalam aplikasi pada Spring Boot. Saya telah mengutip dan membahas argumen utama untuk dan menentang, dan saya juga menyarankan untuk membaca diskusi asli. Masalah ini menunjukkan bahwa sejumlah besar konfigurasi dan default otomatis di Spring / Spring Boot dapat berbahaya bagi pengembang yang lalai.


Apakah Anda menggunakan OSIV dalam aplikasi Boot Musim Semi? Jika tidak, bagaimana arsitektur untuk interaksi lapisan presentasi dengan database diatur? Teknik dan / atau perpustakaan apa yang digunakan untuk ini?

Source: https://habr.com/ru/post/id440734/


All Articles