हाइबरनेट आलसी-लोड एप्लिकेशन डिज़ाइन


87

मैं स्प्रिंग फ्रेमवर्क के साथ संयोजन में हाइबरनेट का उपयोग करने के लिए हूं और यह घोषणात्मक लेनदेन सीमांकन क्षमताओं (जैसे, @ ट्रेंसेक्शनल ) है।

जैसा कि हम सभी जानते हैं, हाइबरनेट गैर-आक्रामक और जितना संभव हो उतना पारदर्शी होने की कोशिश करता है, हालांकि यह रिश्तों को नियोजित करते समय थोड़ा अधिक चुनौतीपूर्ण साबित होता हैlazy-loaded


मैं पारदर्शिता के विभिन्न स्तरों के साथ कई डिज़ाइन विकल्प देखता हूं।

  1. रिश्तों को आलसी-लोडेड न बनाएं (जैसे, fetchType=FetchType.EAGER)
    • यह आलसी लोडिंग के पूरे विचार को दिखाता है।
  2. प्रारंभिक संग्रह का उपयोग कर Hibernate.initialize(proxyObj);
    • इसका मतलब है डीएओ के लिए अपेक्षाकृत उच्च-युग्मन
    • यद्यपि हम एक इंटरफेस को परिभाषित कर सकते हैं initialize, अन्य कार्यान्वयन किसी भी समकक्ष प्रदान करने की गारंटी नहीं है।
  3. Modelखुद को लगातार वस्तुओं के लिए लेनदेन व्यवहार जोड़ें (या तो गतिशील प्रॉक्सी या @Transactional)
    • मैंने डायनेमिक प्रॉक्सी अप्रोच की कोशिश नहीं की है, हालाँकि मुझे कभी भी ऐसा प्रतीत नहीं हुआ कि मैं खुद लगातार वस्तुओं पर काम कर रहा हूं। संभवतया उस हाइबरनेट के साथ एक प्रॉक्सी पर ऑपरेशन किया जा रहा है जिसमें मधुमक्खी हो।
    • नियंत्रण का नुकसान जब लेनदेन वास्तव में हो रहा है
  4. दोनों आलसी / गैर-आलसी एपीआई, जैसे, loadData()औरloadDataWithDeps()
    • कौन सी दिनचर्या को नियोजित करना है, यह जानने के लिए आवेदन को मजबूर करता है, फिर से तंग युग्मन
    • विधि अतिप्रवाह,, loadDataWithA()....,loadDataWithX()
  5. निर्भरता के लिए बल खोज, जैसे, केवल byId()संचालन प्रदान करके
    • इसके बजाय findZzzById(zid), और फिर getYyyIds(zid)इसके बजाय गैर-ऑब्जेक्ट ओरिएंटेड रूटीन की आवश्यकता होती हैz.getY()
    • लेनदेन के बीच एक बड़ा प्रसंस्करण ओवरहेड होने पर, एक-एक करके एक संग्रह में प्रत्येक वस्तु को लाने के लिए उपयोगी हो सकता है।
  6. केवल डीएओ के बजाय आवेदन @ ट्रेंसेक्शनल का हिस्सा बनाएं
    • नेस्टेड लेनदेन के संभावित विचार
    • लेन-देन प्रबंधन के लिए अनुकूलित दिनचर्या की आवश्यकता होती है (जैसे, पर्याप्त रूप से छोटी)
    • छोटे प्रोग्रामेटिक प्रभाव, हालांकि बड़े लेनदेन का परिणाम हो सकता है
  7. डायनेमिक फ़्रेच प्रोफ़ाइल के साथ DAO प्रदान करें , जैसे,loadData(id, fetchProfile);
    • एप्लिकेशन को पता होना चाहिए कि किस प्रोफ़ाइल का उपयोग कब करना है
  8. एओपी प्रकार के लेनदेन, जैसे, संचालन को रोकते हैं और आवश्यक होने पर लेनदेन करते हैं
    • बाइट-कोड हेरफेर या प्रॉक्सी उपयोग की आवश्यकता है
    • लेन-देन करने पर नियंत्रण का नुकसान
    • काला जादू, हमेशा की तरह :)

क्या मुझे कोई विकल्प याद आया?


lazy-loadedआपके एप्लिकेशन डिज़ाइन में रिश्तों के प्रभाव को कम करने की कोशिश करते समय आपका पसंदीदा तरीका कौन सा है ?

(ओह, और WoT के लिए खेद है )


उदाहरण के लिए विकल्प 2 और 5: m-hewedy.blogspot.ch/2010/03/…
Adrien Be

क्या आप विकल्प 4 के लिए एक उदाहरण प्रदान कर सकते हैं?
रात

जवाबों:


26

जैसा कि हम सभी जानते हैं, हाइबरनेट गैर-आक्रामक और यथासंभव पारदर्शी होने की कोशिश करता है

मैं कहूंगा कि शुरुआती धारणा गलत है। ट्रांसपैरेंट दृढ़ता एक मिथक है, क्योंकि एप्लिकेशन को हमेशा इकाई जीवनचक्र का ध्यान रखना चाहिए और ऑब्जेक्ट ग्राफ के आकार को लोड किया जाना चाहिए।

ध्यान दें कि हाइबरनेट विचारों को नहीं पढ़ सकता है, इसलिए यदि आप जानते हैं कि आपको किसी विशेष ऑपरेशन के लिए निर्भरता के एक विशेष सेट की आवश्यकता है, तो आपको किसी तरह हाइबरनेट को अपने इरादे व्यक्त करने की आवश्यकता है।

इस दृष्टिकोण से, इन इरादों को स्पष्ट रूप से व्यक्त करने वाले समाधान (अर्थात्, 2, 4 और 7) उचित लगते हैं और पारदर्शिता की कमी से ग्रस्त नहीं होते हैं।


आप निश्चित रूप से सही हैं, जितना संभव हो उतना पारदर्शी केवल अब तक काम करता है। वे कुछ अच्छे विकल्प हैं जिनके लिए आप गए थे।
जोहान Sjöberg

IMHO: पूरी तरह से सही जवाब। वास्तव में, यह एक मिथक है। BTW: मेरा वोट विकल्प 4 और 7 के लिए होगा (या
ओआरएम

7

मुझे यकीन नहीं है कि आप किस समस्या (आलसीपन के कारण) के लिए इशारा कर रहे हैं, लेकिन मेरे लिए सबसे बड़ा दर्द अपने स्वयं के एप्लिकेशन कैश में सत्र के संदर्भ को खोने से बचाना है। विशिष्ट मामला:

  • ऑब्जेक्ट fooलोड किया गया है और एक नक्शे में डाला गया है;
  • एक अन्य धागा इस ऑब्जेक्ट को नक्शे और कॉल से लेता है foo.getBar()(कुछ ऐसा जिसे पहले कभी नहीं बुलाया गया था और आलसी मूल्यांकन किया गया है);
  • बूम!

इसलिए, इसे संबोधित करने के लिए हमारे पास कई नियम हैं:

  • जितना संभव हो उतना पारदर्शी रूप से सत्र लपेटें (उदाहरण के OpenSessionInViewFilterलिए वेबैप्स);
  • थ्रेड्स / थ्रेड पूल के लिए सामान्य एपीआई है जहाँ db सत्र बाइंड / अनबाइंड पदानुक्रम में कहीं उच्च किया जाता है (लिपटे हुए try/finally) इसलिए उप-वर्ग को इसके बारे में सोचने की ज़रूरत नहीं है;
  • थ्रेड्स के बीच ऑब्जेक्ट्स को पास करते समय, खुद ऑब्जेक्ट्स के बजाय आईडी पास करें। यदि आवश्यक हो तो धागा प्राप्त करना वस्तु को लोड कर सकता है;
  • जब वस्तुओं को कैशिंग किया जाता है, तो कभी भी वस्तुओं को कैश नहीं किया जाता है। जब आप आईडी जानते हैं तो ऑब्जेक्ट को 2 स्तर हाइबरनेट कैश से लोड करने के लिए अपने DAO या प्रबंधक वर्ग में एक सार विधि रखें। द्वितीय स्तर के हाइबरनेट कैश से वस्तुओं को पुनः प्राप्त करने की लागत अभी भी DB की तुलना में काफी सस्ती है।

यह, जैसा कि आप देख सकते हैं, वास्तव में गैर-आक्रामक और पारदर्शी के करीब कहीं नहीं है । लेकिन लागत अभी भी सहने योग्य है, इसकी कीमत के साथ तुलना करने के लिए मुझे उत्सुक लोडिंग के लिए भुगतान करना होगा। उत्तरार्द्ध के साथ समस्या यह है कि कभी-कभी यह एकल प्रभाव वाली वस्तु को लोड करते समय तितली प्रभाव की ओर जाता है, अकेले संस्थाओं का एक संग्रह करते हैं। मेमोरी की खपत, सीपीयू का उपयोग और कम से कम उल्लेख करने की विलंबता भी बहुत खराब है, इसलिए मुझे लगता है कि मैं इसके साथ रह सकता हूं।


आपके जवाब के लिए धन्यवाद। नुकसान की बात transparencyयह है कि आवेदन को आलसी वस्तुओं को लोड करने के लिए मजबूर करने के लिए मजबूर किया जाता है। यदि सब कुछ उत्सुकता से प्राप्त किया गया था, तो आवेदन पूरी तरह से इस बात से अनभिज्ञ हो सकता है कि क्या ऑब्जेक्ट डेटाबेस में बने हुए हैं या नहीं, क्योंकि Foo.getBar()हमेशा सफल होगा। > when passing objects between threads, pass IDs, हाँ, यह # 5 के अनुरूप होगा।
जोहान Sjöberg

3

OpenEntityManagerInViewFilter का उपयोग करने के लिए एक बहुत ही सामान्य पैटर्न हैयदि आप वेब एप्लिकेशन बना रहे हैं तो ।

यदि आप एक सेवा का निर्माण कर रहे हैं, तो मैं डीएओ के बजाय सेवा की सार्वजनिक पद्धति पर TX खोलूंगा, क्योंकि कई बार कई संस्थाओं को प्राप्त करने या अद्यतन करने के लिए एक विधि की आवश्यकता होती है।

यह किसी भी "आलसी लोड अपवाद" को हल करेगा। यदि आपको प्रदर्शन ट्यूनिंग के लिए कुछ और अधिक उन्नत करने की आवश्यकता है, तो मुझे लगता है कि लाने के लिए भ्रूण प्रोफाइल है।


1
मैं तुम्हें कहना चाहता लगता है: एक बहुत ही आम antipattern ... । यद्यपि मैं सेवा स्तर पर TX खोलने से सहमत हूं, लेकिन इसका उपयोग OSIVअभी भी एक एंटीपैटर्न है और अपवाद या प्रदर्शन में गिरावट के साथ सुंदर व्यवहार करने में असमर्थता जैसी गंभीर समस्याओं की ओर जाता है। योग करने के लिए: IMHO OSIV एक आसान उपाय है, लेकिन केवल खिलौना-परियोजनाओं के लिए अच्छा है।
जी। डेमेकी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.