2011-01-12 28 views
7

मैं धारावाहिक डेटा की धारा में "com.newPackage.className" के साथ स्ट्रिंग "com.oldpackage.className" को प्रतिस्थापित करना चाहता हूं। यह धारावाहिक डेटा डीबी से पढ़ा जाता है और स्ट्रिंग को बदलने के बाद अपडेट किया जाता है।धारावाहिक डेटा में कक्षा का नाम बदलना

मुझे ऐसा करने के दौरान कुछ समस्याएं आ रही हैं। यदि आप पहले ही अनुमान लगा चुके हैं, तो यह एक रिफैक्टरिंग अभ्यास का हिस्सा है। क्या कोई पुस्तकालय है जो धारावाहिक डेटा में हेरफेर करने में मेरी मदद करेगा? यदि आप किसी भी सावधानी या चेतावनी पर टिप्पणी भी कर सकते हैं, तो यह बहुत मददगार होगा।

बहुत बहुत धन्यवाद, क्रिस। पीएस: पुरानी कक्षा और नई कक्षा दोनों अपने क्षेत्रों के हिस्से के रूप में एक धारावाहिक आईडी घोषित नहीं करते हैं।

+0

हैं: 1) com.oldPackage बदलें। Com.newPack.Person 2) कॉम/पुरानी पैकेज/कॉम/न्यूपैक/व्यक्ति – ChrisOdney

+0

के साथ व्यक्ति को बदलें क्योंकि com.oldPackage नामक एक क्लास भी है।व्यक्ति विवरण और यह उपर्युक्त परिचालनों से प्रभावित होगा, मैं निम्नलिखित करता हूं: 3) com.newPack.PersonDetails (1 का परिणाम) com.oldPackage.PersonDetails 4) कॉम/न्यूपैक/व्यक्ति विवरण ((परिणाम का परिणाम) 2)) कॉम/पुरानी पैकेज/व्यक्ति विवरण क्या आप कृपया मेरी मदद कर सकते हैं अगर मुझे कुछ याद आ रही है? – ChrisOdney

उत्तर

5

मुझे नहीं पता कि आप क्या कर रहे हैं, लेकिन मैं आपको "कानूनी" समाधान का सुझाव दे सकता हूं। कन्वर्टर को कार्यान्वित करें जिसमें क्लासपाथ में पुराने और नए पैकेज दोनों हैं और निम्न कार्य करता है: डीबी से डेटा पढ़ता है, पुराना पैकेज का उपयोग करके इसे सीरियलाइज करता है, पुराने उदाहरणों को जावा में नए में परिवर्तित करता है और फिर डीबी में फिर से नया डेटा स्टोर करता है।

इस समाधान के लिए कुछ गंदे काम करने की आवश्यकता है लेकिन यह सुरक्षित है। इसके अलावा परिणाम भविष्य में पुन: उपयोग किया जा सकता है। लेकिन मैं आपको समाधान खोजने के लिए शुभकामनाएं देता हूं जो धारावाहिक डेटा में कक्षा के नाम को प्रतिस्थापित करता है।

+0

एलेक्स, यह मेरा पहला दृष्टिकोण था और यह अभी भी जीवित है। लेकिन समस्या यह है कि धारावाहिक डेटा एक हाइबरनेट प्रॉक्सी है और मुझे पहले दृष्टिकोण के साथ बहुत से मुद्दों का सामना करना पड़ रहा है। मुझे serialized डेटा में पैकेज नाम को बदलने के दृष्टिकोण को आसान और सैद्धांतिक रूप से व्यवहार्य माना जाता है, हालांकि, मैं किसी भी चेतावनी या चाल के बारे में सोच रहा हूं जो दूसरों को पता है। – ChrisOdney

+0

ठीक है, शुभकामनाएं। मुझे लगता है कि नाम प्रतिस्थापन शायद काम करेगा यदि पुराने और नए नाम की लंबाई समान है। अन्यथा मैं समस्याओं की उम्मीद कर रहा हूँ। – AlexR

+0

स्पॉट ऑन, मुझे दोनों एसक्यूएल के साथ-साथ जावा पक्ष (जेडीबीसी का उपयोग करके) में प्रतिस्थापन के साथ मुद्दों का सामना करना पड़ा। जावा पक्ष पर यह परिणामसेट से और उसके परिवर्तन के कारण हो सकता था। डीबी में, जिसे मैं बैंकिंग कर रहा था, ने आपके द्वारा उल्लेख किए गए कारणों के लिए बिल्कुल मुद्दों को दिया। – ChrisOdney

1

तो डेटा करने के लिए जा-पुनर्संशोधित संग्रहीत किया जा रहा है - स्ट्रिंग रूप में - एक डेटाबेस में, एक ही विकल्प एसक्यूएल उपयोग करने के लिए बस है कि डेटा, जैसे, (छद्म में MySQL)

update mydata 
set serialized_data = 
replace(serialized_data, "com.oldpackage", "com.newpackage") 
अद्यतन करने के लिए है

डीबी से इस डेटा को फिर से पढ़ने का प्रयास करने से पहले, आप निश्चित रूप से अपने जावा कोड को दोबारा प्रतिक्रिया देंगे।

+0

वह serializable जावा वस्तुओं को स्टोर करता है। क्या आप सुनिश्चित हैं कि सरल स्ट्रिंग प्रतिस्थापन काम करेगा, यानी जावा क्रमबद्धता को तोड़ नहीं देगा? अद्यतन करने के लिए डीबी का उपयोग कर – AlexR

+0

एक अच्छा विचार है! बीबीएस। – ChrisOdney

+1

यह ठीक काम करना चाहिए - धारावाहिक रूप में कोई अन्य जानकारी नहीं है जो अपडेट को विरोधाभास देगी, जो कि मुख्य मुद्दा है, इस धारणा के साथ कि डेटा को फिर से पढ़ने से पहले वास्तविक कोड को दोबारा प्रतिक्रिया दी जाती है। उस रूप में, डेटा स्वयं वर्णन कर रहा है। मैं XStream को एक धारावाहिक/deserializer के रूप में अनुशंसा करता हूं, हालांकि अन्य भी हैं। – kvista

2

आईआईआरसी आप एक अलग पैकेज नामों के साथ Class वापस करने के लिए ObjectInputStream.resolveClass (और resolveProxyClass) ओवरराइड कर सकते हैं (पर्याप्त अनुमतियों के साथ)। हालांकि, आईआईआरसी, आप सरल वर्ग का नाम नहीं बदल सकते हैं।

+0

टॉम, इसे एक एनम पढ़ने के लिए प्रयास करें। – ChrisOdney

+0

और यह जावा जावा डॉट्स के बारे में क्या कहता है: "जिस प्रक्रिया से enum स्थिरांक deserialized हैं अनुकूलित नहीं किया जा सकता है: किसी वर्ग-विशिष्ट readObject, readObjectNoData, और enum प्रकारों द्वारा परिभाषित रीसोलव विधियों को deserialization के दौरान अनदेखा किया जाता है।" – ChrisOdney

+0

@ChrisOdney मैं उन तरीकों का उपयोग करने का सुझाव नहीं दे रहा था। –

1

क्या मैं वैकल्पिक विकल्प का पता लगा सकता हूं। लंबे समय तक भंडारण के लिए इस्तेमाल होने पर जावा क्रमबद्धता प्रारूप में कुछ महत्वपूर्ण मुद्दे हैं।

चूंकि आप रिफैक्टरिंग कर रहे हैं और अधिकतर सभी संग्रहीत डेटा को एक या दूसरे तरीके से deserialise करने की संभावना है, तो आप एक वैकल्पिक धारावाहिक प्रारूप के रूप में Google Protocol Buffers को देखना चाह सकते हैं।

यह थोड़ा और काम ले सकता है लेकिन यह विशेष रूप से दीर्घकालिक भंडारण और संस्करण के लिए डिज़ाइन किया गया है।

गुड लक

+0

गैरेथ, मैं वैकल्पिक धारावाहिक तंत्र के बारे में नहीं सोच सकता जब तक कि मुझे यह वर्तमान डेटा deserialized नहीं मिलता है। – ChrisOdney

+0

निश्चित रूप से केवल एक बार बैच नौकरी में ऑरगिनल कक्षाओं का उपयोग करें? –

2

सटीक टॉम Hawtin का जवाब करने के लिए, मैं निम्नलिखित कोड का उपयोग कर इसे लागू करने में कामयाब रहे:

public static ObjectInputStream getSwapOIS(InputStream in ,String fromClass,String toClass) 
    throws IOException ,ClassNotFoundException { 
    final String from="^"+fromClass,fromArray="^\\[L"+fromClass,toArray="[L"+toClass; 
    return new ObjectInputStream(in) { 
     protected Class<?> resolveClass(ObjectStreamClass desc) 
      throws IOException, ClassNotFoundException 
     { 
      String name = desc.getName().replaceFirst(from, toClass); 
      name = name.replaceFirst(fromArray, toArray); 
      return Class.forName(name); 
     } 
     protected ObjectStreamClass readClassDescriptor() 
      throws IOException, ClassNotFoundException 
     { 
      ObjectStreamClass cd = super.readClassDescriptor(); 
      String name = cd.getName().replaceFirst(from, toClass); 
      name = name.replaceFirst(fromArray, toArray); 
      if(!name.equals(cd.getName())) { 
       cd = ObjectStreamClass.lookup(Class.forName(name)); 
      } 
      return cd; 
     } 
    }; 
} 

ध्यान दें कि आप भी readClassDescriptor ओवरराइड करने के लिए की जरूरत है()। यह मानक प्रकारों और सरणी दोनों के लिए काम करता है और आप कक्षा का नाम भी पैकेज नाम नहीं बदल सकते हैं। बस कार्य करें: enum के नाम com.oldPackage.Person है और नया नाम com.newPack.Person मैं धारावाहिक डेटा में और क्या जगह जाना चाहिए

InputStream in = new ByteArrayInputStream(classBytes); 
ObjectInputStream ois = getSwapOIS( in, 
             "com.oldpackage.className", 
             "com.newpackage.newClassName"); 
Object myObject= ois.readObject(); 
संबंधित मुद्दे