2015-09-18 12 views
7

मैंने सीखा है कि हाइबरनेट आपके वास्तविक इकाई वर्ग का उदाहरण नहीं लौटाता है जब यह आपको एक क्वेरी का परिणाम देता है, लेकिन इसके बजाय एक 'प्रॉक्सी' उदाहरण देता है जो गतिशील रूप से होता है आपकी वास्तविक इकाई की कक्षा से उप-वर्गीकृत। मैं इस व्यवहार के कारण को समझता हूं, क्योंकि यह आलसी प्रारंभिकरण की प्राप्ति के लिए अनुमति देता है। हालांकि, मैं कुछ सवाल इन प्रॉक्सी वर्गों के कार्यान्वयन के विवरण पर अनुत्तरित छोड़ दिया है:हाइबरनेट: प्रॉक्सी कार्यान्वयन का विवरण (आलसी लेटिंग)

  1. आलसी प्राप्त किए गए क्षेत्र ही भरी हुई हो जाएगा जब मैं गेटर का उपयोग करें? यदि मैं फ़ील्ड का उपयोग करता हूं, तो कहें, मेरे equals या hashCode विधि? क्या इन विधियों के निष्पादन के परिणामस्वरूप NullPointerException होगा जब मैंने पहले इस क्षेत्र का गेटटर नहीं कहा था?

  2. जब प्रारंभिकरण शुरू होता है तो हाइबरनेट क्षेत्र को प्रारंभ कैसे करता है? क्या यह फ़ील्ड की सेटर विधि को निष्पादित करता है जिसे मैंने इकाई वर्ग में परिभाषित किया है, या क्या यह प्रतिबिंब के माध्यम से सीधे वैरिएबल को वैल्यू असाइन करेगा या ऐसा कुछ?

उत्तर

1

सबसे पहले, दो नियम:

  1. प्रॉक्सी प्रतिनिधि सभी गैर अंतिम विधि आईडी हो रही है, तो आईडी के लिए संपत्ति का उपयोग मैपिंग में परिभाषित किया गया है के लिए विधि को छोड़कर, लक्ष्य उदाहरण के लिए कहता है।
  2. प्रॉक्सी ऑब्जेक्ट उदाहरण कभी भी प्रारंभ नहीं हुआ, लक्ष्य उदाहरण प्रारंभ किया गया है।

1) मान लीजिए कि आप आह्वान a.equals(b) जहां दोनों a और b एक ही इकाई के प्रॉक्सी कर रहे हैं। और कहते हैं की सुविधा देता है कि equals विधि इस तरह कार्यान्वित किया जाता है:

public boolean equals(Object other) { 
    ... 
    if (this.someField.equals(other.someField)) { 
    ... 
    } 
    ... 
} 

a की equals विधि लक्ष्य उदाहरण अपनी पूरी प्रारंभ मजबूर कर को सौंपा जाता है। तो आप a इंस्टेंस में फ़ील्ड के संबंध में सुरक्षित हैं (आप उन्हें सीधे उपयोग कर सकते हैं)।

हालांकि, क्षेत्रों b उदाहरण (other.someField) में सीधे तक पहुँचने कभी नहीं मान्य है। इससे कोई फर्क नहीं पड़ता कि b प्रारंभ किया गया है या नहीं, प्रॉक्सी इंस्टेंस प्रारंभ नहीं किया गया है, केवल लक्ष्य उदाहरण है। तो, someField उदाहरण में हमेशा null है।

this.someField.equals(other.getSomeField()) 

या एक समान होना चाहिए: - हाइबरनेट नहीं कर सकते

this.getSomeField().equals(other.getSomeField()) 

हालात अलग है जब यह final तरीकों की बात आती हैं

सही कार्यान्वयन other उदाहरण के लिए कम से कम ही टिककर खेल का उपयोग करने के लिए है लक्ष्य को कॉल करने के लिए उन्हें ओवरराइड करें। इसलिए, यदि पिछले उदाहरण में equals विधि final थी, तो this.someField तक पहुंचने पर आपको NullPointerException मिलेगा।

यह सब प्रॉक्सी के बजाय बाइटकोड वाद्ययंत्र का उपयोग करने के लिए हाइबरनेट को कॉन्फ़िगर करके बचाया जा सकता है, लेकिन इसका अपना नुकसान है और इसे व्यापक रूप से अपनाया नहीं जाता है।

2) फिर से, यह कभी प्रॉक्सी इंस्टेंस को प्रारंभ नहीं करता है। जब लक्ष्य उदाहरण प्रारंभिकरण की बात आती है, तो यह निर्भर करता है कि मैपिंग में फ़ील्ड या संपत्ति का उपयोग परिभाषित किया गया है या नहीं। दोनों मामलों में प्रतिबिंब का उपयोग किया जाता है (क्षेत्र पहुंच के मामले में फ़ील्ड को सीधे मूल्यों को निर्दिष्ट करने या संपत्ति पहुंच के मामले में सेटर्स को आमंत्रित करने के लिए)।

संबंधित मुद्दे