2010-03-10 101 views
8

एक चीज़ जो मुझे db4o जैसे किसी ऑब्जेक्ट डेटाबेस का उपयोग करने के बारे में बहुत उलझन में मिली है, यह है कि आप जटिल माइग्रेशन को कैसे संभालना चाहते हैं जो आमतौर पर SQL/PL-SQL द्वारा संभाला जाएगा।ऑब्जेक्ट डेटाबेस में डेटा रखरखाव को संभालना जैसे db4o

उदाहरण के लिए कल्पना करें कि आपके पास my_users नामक एक रिलेशनल डेटाबेस में एक टेबल थी। मूल रूप से आपके पास "full_name" नामक एक कॉलम था, अब आपका सॉफ़्टवेयर वी 2 में है, आप इस कॉलम को हटाना चाहते हैं, रिक्त स्थान पर पूर्ण नाम विभाजित करें और पहले भाग को "first_name" नामक कॉलम में रखें और दूसरा कॉलम में रखें last_name नाम दिया गया। एसक्यूएल में मैं बस "first_name" और "second_name" कॉलम को पॉप्युलेट करता हूं, फिर "full_name" नामक मूल कॉलम को हटा देता हूं।

मैं db4o जैसे कुछ में ऐसा कैसे करूं? क्या मैं जावा प्रोग्राम लिखता हूं जो स्क्रिप्ट्स User.class की सभी ऑब्जेक्ट्स को देखता है, first_name और last_name सेट करते समय पूर्ण_नाम को शून्य पर सेट करता है? जब मैं अपना अगला svn प्रतिबद्ध करता हूं तो पूर्ण_नाम से संबंधित कोई फ़ील्ड/बीन-प्रॉपर्टी नहीं होगी, क्या यह एक समस्या होगी? ऐसा लगता है कि इसे एक उत्पादन अनुप्रयोग में उपयोग करने के लिए प्रतीत होता है जहां मेरा "स्कीमा" बदलता है, मैं संस्करण x से संस्करण x + 1 में डेटा माइग्रेट करने के लिए एक स्क्रिप्ट लिखना चाहता हूं और फिर संस्करण x + 2 में वास्तव में उन गुणों को हटा सकता हूं जिन्हें मैं कोशिश कर रहा हूं संस्करण x + 1 के लिए छुटकारा पाएं क्योंकि मैं उन गुणों को संशोधित करने के लिए जावा स्क्रिप्ट नहीं लिख सकता जो अब मेरे प्रकार का हिस्सा नहीं हैं।

ऐसा लगता है कि समस्या का एक हिस्सा यह है कि एक आरडीबीएमएस हल करता है कि आप एक साधारण केस असंवेदनशील स्ट्रिंग-आधारित नाम के आधार पर किस ऑब्जेक्ट का जिक्र कर रहे हैं, जावा टाइपिंग जैसी भाषा में इससे अधिक जटिल है, आप इसका उल्लेख नहीं कर सकते संपत्ति अगर गेटटर/सेटर/फ़ील्ड रनटाइम पर लोड की गई कक्षा का सदस्य नहीं है, तो आपको अनिवार्य रूप से उसी कोड में अपने कोड के 2 संस्करणों की आवश्यकता होती है (हम्म, कस्टम क्लासलोडर दर्द की तरह ध्वनि), आपके पास नया संस्करण है संग्रहीत कक्षा किसी अन्य पैकेज से संबंधित है (गन्दा लगता है), या मैंने वर्णित संस्करण x + 1 x + 2 रणनीति का उपयोग किया है (बहुत अधिक योजना की आवश्यकता है)। शायद कुछ स्पष्ट समाधान है जो मैंने डीबी 4o दस्तावेजों से कभी नहीं लिया है।

कोई विचार? उम्मीद है कि यह कुछ समझ में आता है।

उत्तर

10

सबसे पहले, डीबी 4o 'सरल' scenarios like adding or removing a field automatically को संभालता है। जब आप फ़ील्ड जोड़ते हैं, तो सभी मौजूदा ऑब्जेक्ट में डिफ़ॉल्ट मान संग्रहीत होता है। जब आप कोई फ़ील्ड हटाते हैं, तो मौजूदा ऑब्जेक्ट का डेटा अभी भी डेटाबेस में है और आप अभी भी इसका उपयोग कर सकते हैं। नामकरण क्षेत्र आदि special 'refactoring'-calls हैं।

अब आप अपने परिदृश्य आप कुछ इस तरह करना होगा:

  1. क्षेत्र 'FULL_NAME' निकालें, नए क्षेत्रों 'first_name' और 'second_name'
  2. सब कुछ खत्म हो दोहराएं जोड़ें 'Address'-वस्तुओं
  3. 'StoredClass'-API
  4. के माध्यम से पुराने फ़ील्ड तक पहुंचें मूल्य को विभाजित करें, बदलें, अपडेट करें आदि। नए फ़ील्ड पर नए मान सेट करें और ऑब्जेक्ट स्टोर करें।

मान लीजिए कि हमारे पास 'पता' श्रेणी है। 'Full_name' फ़ील्ड हटा दिया गया है। अब हम इसे 'फर्स्टनाम' और 'उपनाम' में कॉपी नहीं करना चाहते हैं। तो यह इस (जावा) की तरह जा सकते हैं:

ObjectSet<Address> addresses = db.query(Address.class); 
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class); 
    for (Address address : addresses) { 
     String fullName = (String)metaInfoOfField.get(address); 
     String[] splitName = fullName.split(" "); 
     address.setFirstname(splitName[0]); 
     address.setSurname(splitName[1]); 
     db.store(address); 
    } 

आप सुझाव के रूप में, आप प्रत्येक संस्करण-टक्कर के लिए माइग्रेशन-कोड लिखेंगे। यह क्षेत्र अब आपकी कक्षा का हिस्सा नहीं है, आपको इसे 'स्टोर्डफ़िल्ल्ड' -पीआई के साथ एक्सेस करना होगा।

आप ObjectContainer.ext().storedClasses() के साथ सभी 'संग्रहीत' कक्षाओं की एक सूची प्राप्त कर सकते हैं। StoredClass.getStoredFields() के साथ आप सभी स्टोर फ़ील्ड की एक सूची प्राप्त कर सकते हैं, कोई माथेर नहीं है कि फ़ील्ड अब आपकी कक्षा में मौजूद नहीं है। यदि कोई कक्षा अब मौजूद नहीं है, तो आप अभी भी ऑब्जेक्ट प्राप्त कर सकते हैं और इसे 'जेनेरिक ऑब्जेक्ट'-क्लास के माध्यम से एक्सेस कर सकते हैं।

अपडेट: जटिल परिदृश्यों के लिए जहां डेटाबेस को एकाधिक-संस्करण-चरणों पर माइग्रेट करने की आवश्यकता होती है।

उदाहरण के लिए यह संस्करण v3 में पता-ऑब्जेक्ट पूरी तरह से अलग दिखता है। तो v1 से v2 के लिए 'माइग्रेशन-स्क्रिप्ट' फ़ील्ड को अब और फ़ील्ड नहीं मिला है (इसके पहले उदाहरण में मेरा नाम और निश्चित नाम)। मुझे लगता है कि इसे संभालने के लिए कई संभावनाएं हैं।

  1. (इस विचार के लिए जावा मानना। निश्चित रूप से .NET में समतुल्य है)। आप माइग्रेशन-चरण Groovy-script बना सकते हैं। तो प्रत्येक जो प्रत्येक स्क्रिप्ट किसी दूसरे के साथ हस्तक्षेप नहीं करता है। फिर आप माइग्रेशन के लिए आवश्यक कक्षाओं को 'वर्ग' परिभाषित करते हैं। इसलिए प्रत्येक माइग्रेशन में अपना माइग्रेशन-क्लास होता है। aliases के साथ आप वास्तविक जावा-कक्षाओं में अपने ग्रोवी-माइग्रेशन-क्लासेस को बाध्य करेंगे।
  2. जटिल परिदृश्यों के लिए रिफैक्टरिंग-क्लासेस बनाना। aliases के साथ इस कक्षा को भी बांधें।
2

मैं यहां एक जंगली शॉट ले रहा हूं, क्योंकि मैंने अपने जीवन में बहुत अधिक डेटा को दोबारा नहीं बदला है।

आप एक अजीब तुलना कर रहे हैं: यदि आप डीबी को 'हॉट-माइग्रेट' करना चाहते हैं, तो आपको शायद x+1, x+2 आपके द्वारा वर्णित संस्करण दृष्टिकोण को करना होगा, लेकिन मुझे वास्तव में पता नहीं है - मैं नहीं चाहता यह नहीं पता कि एसक्यूएल के साथ ऐसा कैसे करें क्योंकि मैं एक डीबी विशेषज्ञ नहीं हूं।

यदि आप 'ठंडा' माइग्रेट कर रहे हैं, तो आप पुराने डेटा से एक नई वस्तु को तुरंत चालू करके, नई वस्तु को स्टोर करके, स्टोर में प्रत्येक ऑब्जेक्ट के लिए पुरानी वस्तु को हटाकर एक चरण में ऐसा कर सकते हैं। db4o reference देखें।

लेकिन ईमानदारी से: आरडीबीएमएस में एक ही प्रक्रिया जटिल है, क्योंकि आपको वास्तव में ऑपरेशन करने के लिए बाधा जांच (और संभवतः ट्रिगर्स इत्यादि) को सक्रिय करना होगा - शायद आपके द्वारा प्रदान किए गए उदाहरण में नहीं, लेकिन ज्यादातर वास्तविक दुनिया के मामलों के लिए। आखिरकार, स्ट्रिंग स्प्लिट इतना आसान है कि थोड़ा लाभ होगा।

एसक्यूएल में मैं बस, "first_name" और "second_name" कॉलम

हाँ हो जाएगी एक सरल स्ट्रिंग विभाजन आपरेशन के साथ, आप बस ऐसा कर सकते हैं। लेकिन एक ठेठ रिफैक्टरिंग परिदृश्य में, आप उन नियमों के बड़े और जटिल सेटों के आधार पर ऑब्जेक्ट्स को पुन: संरचना कर रहे हैं जिन्हें SQL में आसानी से व्यक्त नहीं किया जा सकता है, जटिल गणना या बाहरी डेटा स्रोतों की आवश्यकता हो सकती है।

ऐसा करने के लिए, आपको भी कोड लिखना होगा।

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