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.

OpenSessionInViewFilterAramaları openSessiontemel yöntemi SessionFactoryve yeni elde Session.
-
SessionBağlıdır TransactionSynchronizationManager.
-
OpenSessionInViewFilterAramaları doFilterbir javax.servlet.FilterChainamacı, referans ve daha ayrıntılı işlenir
-
DispatcherServletDenir ve altta yatan için bu yolları HTTP isteği olduğunu PostController.
-
PostControllerÇağrılar PostServicelistesini almak için Postkişiler.
-
PostServiceYeni bir işlem açar ve HibernateTransactionManageraynı yeniden kullanır Sessiontarafından açıldığını OpenSessionInViewFilter.
PostDAOListesini getirir Postherhangi tembel ilişki başlatılıyor dışındaki varlıklar.
-
PostServiceAltında yatan işlem taahhüt, ama Sessiono 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.
OpenSessionInViewFilterKapatabilir Sessionve 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, @BatchSizeilişkilendirmeleri toplu olarak FetchMode.SUBSELECTgetirmeyi 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.propertiesyapı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 .