OSIV Anti-Pattern
Görünüm katmanının ihtiyaç duyduğu tüm ilişkilendirmeleri en iyi nasıl getireceğine iş katmanının karar vermesine izin vermek yerine, OSIV (Görünümde Açık Oturum) Kalıcı Bağlamı açık kalmaya zorlar, böylece Görünüm katmanı Proxy başlatmayı tetikleyebilir. aşağıdaki diyagram ile.
OpenSessionInViewFilter
Aramaları openSession
temel yöntemi SessionFactory
ve yeni elde Session
.
-
Session
Bağlıdır TransactionSynchronizationManager
.
-
OpenSessionInViewFilter
Aramaları doFilter
bir javax.servlet.FilterChain
amacı, referans ve daha ayrıntılı işlenir
-
DispatcherServlet
Denir ve altta yatan için bu yolları HTTP isteği olduğunu PostController
.
-
PostController
Çağrılar PostService
listesini almak için Post
kişiler.
-
PostService
Yeni bir işlem açar ve HibernateTransactionManager
aynı yeniden kullanır Session
tarafından açıldığını OpenSessionInViewFilter
.
PostDAO
Listesini getirir Post
herhangi tembel ilişki başlatılıyor dışındaki varlıklar.
-
PostService
Altında yatan işlem taahhüt, ama Session
o dışarıdan açıldı çünkü kapalı değil.
- Başlangıçlar
DispatcherServlet
, sırayla tembel ilişkilendirmelerde gezinen ve başlatılmalarını tetikleyen kullanıcı arayüzünü oluşturmaya başlar.
OpenSessionInViewFilter
Kapatabilir Session
ve altta yatan veritabanı bağlantısı sıra serbest bırakılır.
İlk bakışta, bu yapılacak çok kötü bir şey gibi görünmeyebilir, ancak bir veritabanı perspektifinden baktığınızda, bir dizi kusur daha belirgin hale gelmeye başlar.
Hizmet katmanı bir veritabanı işlemini açar ve kapatır, ancak daha sonra devam eden açık bir işlem yoktur. Bu nedenle, kullanıcı arabirimi oluşturma aşamasından yayınlanan her ek ifade, otomatik kesinleştirme modunda yürütülür. Otomatik kesinleştirme, veritabanı sunucusuna baskı uygular, çünkü her bir ifade işlem günlüğünü diske aktarmalıdır, bu nedenle veritabanı tarafında çok fazla G / Ç trafiğine neden olur. Optimizasyonlardan biri Connection
, veritabanı sunucusunun işlem günlüğüne yazmaktan kaçınmasına izin verecek şekilde salt okunur olarak işaretlemek olacaktır.
Artık endişelerin ayrılması yok çünkü ifadeler hem hizmet katmanı hem de UI oluşturma işlemi tarafından üretiliyor. Üretilen ifadelerin sayısını belirten entegrasyon testleri yazmak , uygulamayı bir web kapsayıcısına yerleştirirken tüm katmanlardan (web, hizmet, DAO) geçmeyi gerektirir. Bir bellek içi veritabanı (ör. HSQLDB) ve hafif bir web sunucusu (ör. Jetty) kullanıldığında bile, bu entegrasyon testlerinin yürütülmesi, katmanların ayrılmasına ve arka uç entegrasyon testlerinin veritabanını kullanmasına göre daha yavaş olacaktır. ön uç entegrasyon testleri, hizmet katmanını tamamen alay ediyordu.
UI katmanı, sırayla N + 1 sorgu problemlerini tetikleyebilecek gezinme ilişkileri ile sınırlıdır . Hibernate, @BatchSize
ilişkilendirmeleri toplu olarak FetchMode.SUBSELECT
getirmeyi ve bu senaryoyla başa çıkmayı teklif etse de , ek açıklamalar varsayılan getirme planını etkilediğinden, her iş kullanım durumuna uygulanır. Bu nedenle, bir veri erişim katmanı sorgusu çok daha uygundur çünkü mevcut kullanım durumu veri getirme gereksinimlerine göre uyarlanabilir.
Son olarak, veritabanı bağlantısı, UI oluşturma aşaması boyunca tutulur, bu da bağlantı kiralama süresini artırır ve veritabanı bağlantı havuzundaki tıkanıklık nedeniyle toplam işlem hacmini sınırlar. Bağlantı ne kadar tutulursa, havuzdan bağlantı almak için eşzamanlı talepler o kadar fazla bekleyecektir.
Spring Boot ve OSIV
Maalesef OSIV (Görünümde Açık Oturum), Spring Boot'ta varsayılan olarak etkindir ve OSIV, performans ve ölçeklenebilirlik açısından gerçekten kötü bir fikirdir .
Bu nedenle, application.properties
yapılandırma dosyasında aşağıdaki girişe sahip olduğunuzdan emin olun :
spring.jpa.open-in-view=false
Bu, OSIV'i devre dışı bırakacak ve böylece doğru şekilde idareLazyInitializationException
edebileceksiniz .
Sürüm 2.0'dan başlayarak, Spring Boot , OSIV varsayılan olarak etkinleştirildiğinde bir uyarı verir , böylece bu sorunu bir üretim sistemini etkilemeden çok önce keşfedebilirsiniz.
OSIV hakkında daha fazla ayrıntı için bu makaleye göz atın .