OSIV एंटी-पैटर्न
व्यापार परत को यह तय करने के बजाय कि व्यू लेयर द्वारा आवश्यक सभी संघों को कैसे प्राप्त करना सबसे अच्छा है, OSIV (ओपन सेशन इन व्यू) दृढ़ता के संदर्भ में खुले रहने के लिए बाध्य करता है, ताकि दृश्य परत प्रॉक्सी आरंभीकरण को ट्रिगर कर सके, जैसा कि सचित्र है निम्नलिखित चित्र द्वारा।
OpenSessionInViewFilter
कॉल openSession
अंतर्निहित की विधि SessionFactory
और एक नया प्राप्त Session
।
- के
Session
लिए बाध्य है TransactionSynchronizationManager
।
OpenSessionInViewFilter
कॉल doFilter
की javax.servlet.FilterChain
वस्तु संदर्भ और अनुरोध आगे संसाधित किया जाता है
DispatcherServlet
कहा जाता है, और अंतर्निहित करने के लिए इसे मार्गों HTTP अनुरोध PostController
।
PostController
कॉल PostService
की एक सूची प्राप्त करने के लिए Post
संस्थाओं।
PostService
एक नई लेन-देन को खोलता है, और HibernateTransactionManager
एक ही पुनः उपयोग कर लेता Session
है कि द्वारा खोला गया था OpenSessionInViewFilter
।
PostDAO
की सूची को हासिल करेगा Post
किसी भी आलसी संघ आरंभ बिना संस्थाओं।
PostService
अंतर्निहित लेन-देन करता है, लेकिन Session
बंद नहीं है, क्योंकि यह बाह्य खोला गया था।
DispatcherServlet
शुरू होता है यूआई, जो, बारी में, आलसी संघों नेविगेट करता है और उनके प्रारंभ से चलाता है प्रतिपादन।
OpenSessionInViewFilter
बंद कर सकते हैं Session
, और अंतर्निहित डेटाबेस कनेक्शन में अच्छी तरह से जारी किया गया है।
पहली नज़र में, यह करने के लिए एक भयानक बात की तरह नहीं लग सकता है, लेकिन, एक बार जब आप इसे डेटाबेस के दृष्टिकोण से देखते हैं, तो दोषों की एक श्रृंखला अधिक स्पष्ट होने लगती है।
सेवा परत डेटाबेस लेनदेन को खोलता और बंद करता है, लेकिन बाद में, कोई स्पष्ट लेनदेन नहीं होता है। इस कारण से, UI रेंडरिंग चरण से जारी किए गए प्रत्येक अतिरिक्त विवरण को ऑटो-कमिट मोड में निष्पादित किया जाता है। ऑटो-कमेट डेटाबेस सर्वर पर दबाव डालता है क्योंकि प्रत्येक स्टेटमेंट में ट्रांजेक्शन लॉग को डिस्क में फ्लश करना चाहिए, इसलिए डेटाबेस साइड पर बहुत सारे I / O ट्रैफिक का कारण बनता है। एक अनुकूलन के Connection
रूप में केवल पढ़ने के लिए चिह्नित किया जाएगा जो डेटाबेस सर्वर को लेनदेन लॉग में लिखने से बचने की अनुमति देगा।
अब चिंताओं का कोई पृथक्करण नहीं है क्योंकि कथन सेवा परत और UI रेंडरिंग प्रक्रिया दोनों द्वारा उत्पन्न होते हैं। एकीकरण परीक्षण लिखना जो उत्पन्न होने वाले बयानों की संख्या को बढ़ाता है, वेब कंटेनर पर तैनात होने के दौरान सभी परतों (वेब, सेवा, डीएओ) के माध्यम से जाने की आवश्यकता होती है। इन-मेमोरी डेटाबेस (जैसे एचएसक्यूएलडीबी) और एक हल्के वेब सर्वर (जैसे जेट्टी) का उपयोग करते समय भी, इन एकीकरण परीक्षणों को निष्पादित करने की तुलना में धीमी होने जा रही है यदि परतें अलग हो गई थीं और बैक-एंड एकीकरण परीक्षण डेटाबेस का उपयोग करते थे, जबकि फ्रंट-एंड इंटीग्रेशन टेस्ट पूरी तरह से सर्विस लेयर का मजाक उड़ा रहे थे।
यूआई परत नेविगेट करने वाले संघों तक सीमित है, जो बदले में, एन + 1 क्वेरी समस्याओं को ट्रिगर कर सकती है । यद्यपि हाइबरनेट @BatchSize
बैचों में संघों को लाने के लिए प्रदान करता है , और FetchMode.SUBSELECT
इस परिदृश्य के साथ सामना करने के लिए, एनोटेशन डिफ़ॉल्ट रूप से लाने की योजना को प्रभावित कर रहे हैं, इसलिए वे हर व्यवसाय उपयोग के मामले में लागू होते हैं। इस कारण से, डेटा एक्सेस लेयर क्वेरी बहुत अधिक उपयुक्त है क्योंकि इसे वर्तमान उपयोग के मामले में डेटा की आवश्यकताओं के अनुरूप बनाया जा सकता है।
अंतिम लेकिन कम से कम, डेटाबेस कनेक्शन पूरे यूआई रेंडरिंग चरण में आयोजित किया जाता है जो कनेक्शन लीज समय को बढ़ाता है और डेटाबेस कनेक्शन पूल पर भीड़ के कारण समग्र लेनदेन थ्रूपुट को सीमित करता है। जितना अधिक कनेक्शन आयोजित किया जाता है, उतना ही अन्य समवर्ती अनुरोध पूल से कनेक्शन प्राप्त करने के लिए इंतजार करने वाले हैं।
स्प्रिंग बूट और OSIV
दुर्भाग्य से, OSIV (ओपन सेशन इन व्यू) स्प्रिंग बूट में डिफ़ॉल्ट रूप से सक्षम है , और OSIV वास्तव में एक प्रदर्शन और मापनीयता के दृष्टिकोण से एक बुरा विचार है ।
इसलिए, सुनिश्चित करें कि application.properties
कॉन्फ़िगरेशन फ़ाइल में, आपके पास निम्न प्रविष्टि है:
spring.jpa.open-in-view=false
यह OSIV को अक्षम कर देगा ताकि आप सही तरीके से संभालLazyInitializationException
सकें ।
संस्करण 2.0 से शुरू होकर, स्प्रिंग बूट एक चेतावनी जारी करता है जब OSIV डिफ़ॉल्ट रूप से सक्षम होता है, इसलिए उत्पादन प्रणाली को प्रभावित करने से पहले आप इस समस्या का पता लगा सकते हैं।
OSIV के बारे में अधिक जानकारी के लिए, इस लेख को देखें ।