2012-04-15 24 views
6

मैं यहां एक नुकसान में हूं, और शायद यह कुछ स्पष्ट है क्योंकि मेरी हाइबरनेट विशेषज्ञता अन्य क्षेत्रों की तुलना में कमजोर है।हाइबरनेट मौजूदा डेटा माइग्रेट करने के लिए एम्बेड करने योग्य वर्ग को स्वैप आउट करें

विरासत कोड में एक हाइबरनेट @Entity कक्षा Foo है।

private OldBar bar = new OldBar(); 

OldBar एक @Embeddable वर्ग एकल स्तंभ, foobar का उपयोग करता है:

@Embeddable 
public class OldBar { 

    private String fooBar; 

    @Column(length = 10, nullable = false) 
    private String getFooBar() { 
    return fooBar; 
    } 

    @SuppressWarnings("unused") 
    private void setFooBar(String fooBar) { 
    this.fooBar = fooBar; 
    } 
} 

मूल समस्या यह है कि मैं OldBar.fooBar साथ कुछ करने की जरूरत है, लेकिन इसके गुणों में से एक यह है मूल डिजाइन में सीमाएं थीं और मुझे यह क्षेत्र निजी था, मुझे इसे सबक्लासिंग से रोक रहा था, इसलिए मुझे एक और अन्य वर्ग, NewBar बनाना था, दूसरे को बदलने और निजी क्षेत्र तक पहुंच प्राप्त करना था। मैंने सोचा था कि के बाद से NewBar भी Embeddable है और एक ही @Column पद है, मैं सिर्फ बाहर क्षेत्र वर्ग Foo में स्वैप कर सकते हैं:

private NewBar bar = new NewBar(); 

मैं क्योंकि मैं foobar कॉलम में मौजूदा डेटा है यह करने के लिए चाहते थे, और मैं OldBar के बजाय NewBar के साथ पारदर्शी रूप से इस डेटा का उपयोग करना चाहता था।

ट्रेस लॉग के माध्यम से मैंने देखा है कि Foo()NewBar() के डिफ़ॉल्ट संस्करण के साथ बनाया गया है, जैसा कि कोई उम्मीद करेगा, जब निर्माता को बुलाया जाता है। हालांकि, समय कोड Foo.getBar() पर कॉल करता है, किसी कारण से barnull है! मुझे लगता है कि हाइबरनेट इसे किसी कारण से null पर सेट कर रहा है --- लेकिन foobar कॉलम से डेटा पढ़ने और NewBar का उदाहरण क्यों नहीं बना रहा है? जब मैं के स्थान पर OldBar डालता हूं तो यह फिर से काम क्यों करता है? निश्चित रूप से डेटाबेस में कुछ भी नहीं है जो कहता है कि @Embeddable कक्षाओं में से कौन सा कॉलम पर मैप किया गया है, है ना?

अद्यतन: यह अजनबी और अजनबी हो जाता है। कभी-कभी मैं रात भर कोड दूंगा, और अगले दिन यह काम करता है! या अगले दिन यह काम नहीं करता है! अभी यह काम नहीं कर रहा है (यानी, foobar संपत्ति डेटाबेस में मान के बजाय null पर सेट की गई थी), इसलिए मैंने ExactCopyOfOldBar कक्षा बनाई और इसे OldBar के स्थान पर रखा। यह ठीक काम किया! इसलिए मैं NewBar पर वापस स्विच करता हूं --- केवल मेरे अस्थायी परिवर्तनों को पूर्ववत करता हूं। यह अभी भी काम करता था, जब यह पहले नहीं था! क्या वहां कुछ प्रकार का कैश है जहां हाइबरनेट मूल्यों को क्रमबद्ध करता है और उन्हें डेटाबेस से नहीं मिलता है? यह बहुत अजीब है।

अद्यतन: अब मुझे काम करने के लिए NewBar नहीं मिल सकता है। मैं OtherBar बना देता हूं, जो मूल रूप से NewBar के समान है, सिवाय इसके कि इसका एक अलग नाम है, और मैं इसे प्लग करता हूं और यह काम करता है, एम्बेडेड स्ट्रिंग को सही ढंग से पढ़ता है। मैं NewBar पर वापस स्विच करता हूं, और मुझे null फिर से मिलता है। क्या हो रहा है?

ध्यान दें कि Foonet.databinder.auth.hib.AuthDataApplication.getUser(String username) के माध्यम से लोड किया जा रहा है, जो काफी सरल है:

return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass()) 
    .add(Restrictions.eq("username", username)).uniqueResult(); 

मैं Foo (उपयोगकर्ता) की मेज, सही डेटा के साथ एक ही पंक्ति है कि अधिक सत्यापित करने के बाद बार-बार और सबसे महत्वपूर्ण बात यह है कि foobar फ़ील्ड में डेटा है। Hibernate मुझे Foo पर nullfoobar फ़ील्ड के साथ क्यों लौटा रहा है? NewBar से OtherBar पर स्विच करने से यह फिर से काम करना शुरू कर देता है? यह पूरे दिन क्यों काम करता है और फिर रात भर छोड़ने के बाद काम करना बंद कर देता है?

+0

मुझे लगता है कि यह सच है, लेकिन आपने यह नहीं कहा: क्या 'Foo.bar' '@ एम्बेडेड' के रूप में चिह्नित है? –

+0

@ टिम पोटे: असल में, आश्चर्यजनक रूप से पर्याप्त, मूल (कामकाजी) विरासत कोड में, यह _not_ को '@ एम्बेडेड' के रूप में चिह्नित किया गया था। जब मैंने 'ओल्डबार' को 'न्यूबार' में बदल दिया, तो मैंने इसे '@ एम्बेडेड' के साथ और बिना कोशिश की, और इससे कोई फर्क नहीं पड़ता। –

+0

@ टिम पोटे: मैंने हाइबरनेट [दस्तावेज़ीकरण] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/) से सीखा है कि "... यदि संपत्ति का प्रकार @Embeddable के रूप में एनोटेटेड है, इसे @Embedded के रूप में मैप किया गया है, "इसलिए तकनीकी रूप से' @ एम्बेडेड' भाग वैकल्पिक है। –

उत्तर

1

यह उत्तर हो सकता है; मुझे यह देखने के लिए कई दिन इंतजार करना होगा कि क्या यह वास्तव में समस्या को हल करता है या नहीं। वास्तव में दो भाग हैं।

सबसे पहले, पूर्ण प्रकटीकरण के लिए, मेरी NewBar कक्षा वास्तव में AbstractBar का उप-वर्ग था। मैं अंततः विभिन्न प्रकार के एम्बेड करने योग्य सलाखों को चाहता था, इसलिए मैंने स्तर पर @Embeddable पर NewBar स्तर पर स्तर पर रखा, और निजी foobar फ़ील्ड को AbstractBar स्तर पर भी रखा। मजाकिया बात यह है कि, इसने कुछ समय काम किया। और जैसा कि मैंने उल्लेख किया है, कभी-कभी मैं अगले दिन वापस आऊंगा और हाइबरनेट foobar फ़ील्ड लोड नहीं करेगा। मुझे समझ में नहीं आता कि यह हर समय क्यों काम नहीं करता था या किसी भी समय काम नहीं करता था।

दूसरे, जब मैं इस पदानुक्रम से छुटकारा पाने के इतनी के रूप में समस्या का एक स्रोत को खत्म करने की कोशिश की, मैं AbstractBar और NewBar सम्मिश्रित लेकिन @Embeddable अप AbstractBar से NewBar में लाने के लिए भूल गया, तो हाइबरनेट नहीं देखा था कि एक एम्बेड करने योग्य वर्ग, और पदनाम के बिना NewBar फ़ील्ड में स्ट्रिंग को लोड करने का तरीका नहीं पता था। यही कारण है कि OtherBar (@Embeddable एनोटेशन के साथ) काम किया, लेकिन NewBar नहीं (@Embeddable एनोटेशन के साथ)। मैं इतना समझता हूं। क्यों हाइबरनेट ने मुझे चेतावनी नहीं दी कि यह पता नहीं लगा सकता कि मैदान कैसे लोड किया जाए, मुझे नहीं पता।

तो सारांशित करने के लिए, यदि आपने कक्षा से @Embeddable एनोटेशन छोड़ा है तो हाइबरनेट एक एम्बेड करने योग्य फ़ील्ड लोड नहीं करेगा। मूल समस्या के लिए, मैं केवल अनुमान लगा सकता हूं कि @Embeddable क्लास पदानुक्रम पर इसका उपयोग करने की कोशिश करते समय flaky है, और यह कि आप अपने सभी एम्बेड करने योग्य फ़ील्ड को एम्बेड करने योग्य वर्ग में एक स्तर पर रखने से सबसे अच्छे हैं। मुझे उम्मीद है कि यह मुद्दा है। हम देखेंगे कि यह कल काम करना जारी रखता है या नहीं।