2009-05-07 17 views
14

मेरे पास एक साधारण जावा POJO है कि मैं गुणों को एक ही पीओजेओ कक्षा के दूसरे उदाहरण में कॉपी करूंगा।एक जावा बीन से दूसरे गुणों की प्रतिलिपि कैसे करें?

मुझे पता है कि मैं इसे BeanUtils.copyProperties() के साथ कर सकता हूं लेकिन मैं किसी तृतीय-पक्ष लाइब्रेरी के उपयोग से बचना चाहता हूं।

तो, यह कैसे करें, उचित और सुरक्षित तरीका कैसे करें?

वैसे, मैं जावा 6.

+8

उम, बीनयूटिल्स.पीपीप्रॉपर्टीज() * उचित तरीका है। यह उस पुस्तकालय में है क्योंकि इसे अन्यथा करने का कोई आसान तरीका नहीं है। यदि आप वास्तव में BeanUtils का उपयोग नहीं करना चाहते हैं, तो उसके लिए स्रोत कोड डाउनलोड करें, और विधि कॉपी करें। – skaffman

+1

skaffman - जब मैंने अपना जवाब पोस्ट किया, तो मुझे आपकी टिप्पणी नहीं मिली, क्षमा करें। लेकिन जैसा कि आप देख सकते हैं मैं पूरी तरह से आपसे सहमत हूं :) – MetroidFan2002

+1

ध्यान दें कि वसंत में एक [बीनयूटिल्स.पीपीप्रॉपर्टीज] भी शामिल है (http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans /BeanUtils.html) विधि जो अधिक सुविधाजनक हो सकती है यदि आप पहले से ही वसंत का उपयोग कर रहे हैं। – pimlottc

उत्तर

12

मुझे लगता है कि अगर आप BeanUtils के स्रोत कोड को देखने का उपयोग कर रहा है, यह बताएंगे कि कैसे वास्तव में BeanUtils का उपयोग किए बिना ऐसा करने के लिए होगा।

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

+1

यदि सभी गुणों को फ़ील्ड द्वारा समर्थित किया जाता है, तो इसे क्लोनेबल को अच्छी तरह से करना चाहिए, और यह बहुत ही कुशल है। हालांकि, ध्यान दें कि यह एक उथली प्रतिलिपि है ... –

+1

यह एक उथली प्रतिलिपि है यदि आप इसे सार्वजनिक बनाने और अभिभावक कार्यान्वयन को कॉल करने के लिए केवल क्लोनेबल और ओवरड क्लोन() को लागू करते हैं। लेकिन निश्चित रूप से, आप गहरी प्रतिलिपि बनाने सहित कुछ भी करने के लिए क्लोन() को कार्यान्वित कर सकते हैं। क्लोन() के बारे में और जानकारी के लिए 'प्रभावी जावा' देखें। –

2

JavaBeans API पर विशेष रूप से Introspector कक्षा पर एक नज़र डालें। आप BeanInfo मेटाडेटा का उपयोग get और set गुणों का उपयोग कर सकते हैं। यदि आप पहले से नहीं हैं तो JavaBeans specification पर पढ़ना एक अच्छा विचार है। यह reflection API के साथ गुजरने की परिचितता में भी मदद करता है।

+0

अच्छी सलाह है, लेकिन शायद उन सभी के अंतिम परिणाम को मानने के लिए उचित है जो संभवतः बीनयूटिल्स.copyProperties() –

+0

का एक निम्न कार्यान्वयन होगा, यह एक उचित टिप्पणी है, लेकिन यह जानने के लिए कभी दर्द नहीं होता कि क्या हो रहा है। – McDowell

+0

Thx। मैं जावा 6 के साथ नया हूं इसलिए मुझे उम्मीद थी कि पिछले संस्करणों की तुलना में यह अधिक आसानी से करने का एक तरीका होगा। लेकिन मैं निश्चित रूप से आपके लिंक पर एक नज़र डालेगा। – paulgreg

1

ऐसा करने का कोई आसान तरीका नहीं है। इंट्रोस्पेक्टर और जावा बीन्स लाइब्रेरी मोनोलिथिक हैं - बीनयूटिल्स इसके चारों ओर एक साधारण आवरण है और अच्छी तरह से काम करता है। लाइब्रेरी नहीं होने के लिए पुस्तकालयों में सामान्य रूप से एक बुरा विचार नहीं है - जावा के साथ मौजूद सामान्य कार्यक्षमता - सामान्य कार्यक्षमता के साथ शुरू करने के लिए एक कारण है, लेकिन ऐसा नहीं है।

10

Google App Engine के लिए ऐप विकसित करते समय मुझे भी यही समस्या थी, जहां मैं कॉमन्स लॉगिंग प्रतिबंधों के कारण बीनयूटिल का उपयोग नहीं कर सका। वैसे भी, मैं इस समाधान के साथ आया और मेरे लिए बस ठीक काम किया।

public static void copyProperties(Object fromObj, Object toObj) { 
    Class<? extends Object> fromClass = fromObj.getClass(); 
    Class<? extends Object> toClass = toObj.getClass(); 

    try { 
     BeanInfo fromBean = Introspector.getBeanInfo(fromClass); 
     BeanInfo toBean = Introspector.getBeanInfo(toClass); 

     PropertyDescriptor[] toPd = toBean.getPropertyDescriptors(); 
     List<PropertyDescriptor> fromPd = Arrays.asList(fromBean 
       .getPropertyDescriptors()); 

     for (PropertyDescriptor propertyDescriptor : toPd) { 
      propertyDescriptor.getDisplayName(); 
      PropertyDescriptor pd = fromPd.get(fromPd 
        .indexOf(propertyDescriptor)); 
      if (pd.getDisplayName().equals(
        propertyDescriptor.getDisplayName()) 
        && !pd.getDisplayName().equals("class")) { 
       if(propertyDescriptor.getWriteMethod() != null)     
         propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null)); 
      } 

     } 
    } catch (IntrospectionException e) { 
     e.printStackTrace(); 
    } catch (IllegalArgumentException e) { 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     e.printStackTrace(); 
    } 
} 

कोई भी संवर्धन या संशोधन वास्तव में स्वागत है।

+1

धन्यवाद, आपने मुझे इस प्रश्न के साथ मदद की: http://stackoverflow.com/questions/8384814/when-can-propertyutils-copyproperties-fail- मैं आपको सुझाव देता हूं कि आप केवल पढ़ने-योग्य गुणों के लिए समर्थन जोड़कर जांच करें कि 'propertyDescriptor.getWriteMethod() 'शून्य वापस आता है। – ripper234

+1

सिफारिश के लिए धन्यवाद। मैंने केवल पढ़ने के गुणों के लिए समर्थन जोड़ने के लिए अपना जवाब संपादित किया। – Efthymis

1

मैं Introspector.getBeanInfo के साथ कुछ समस्याओं में भाग गया, सभी गुणों को वापस नहीं लौटा, इसलिए मैंने संपत्ति प्रतिलिपि के बजाय एक फील्ड प्रति लागू करना समाप्त कर दिया।

public static <T> void copyFields(T target, T source) throws Exception{ 
    Class<?> clazz = source.getClass(); 

    for (Field field : clazz.getFields()) { 
     Object value = field.get(source); 
     field.set(target, value); 
    } 
} 
2

एक अन्य विकल्प MapStruct किस प्रकार सुरक्षित मैपिंग जो रनटाइम पर किसी भी निर्भरता की आवश्यकता नहीं है, जिसके परिणामस्वरूप निर्माण समय में मानचित्रण कोड उत्पन्न करता है, है (अस्वीकरण: मैं MapStruct के लेखक हूँ)।

3

हे दोस्तों सिर्फ एक ही बीन मानों को कॉपी करने के लिए एक ही समान बीन की प्रतिलिपि बनाने के लिए मेरे बनाए गए प्रतिबिंब उपयोग कक्षा का उपयोग करें। यह कक्षा संग्रह ऑब्जेक्ट की प्रतिलिपि भी करेगी।

https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java

नोट: यह सेम प्रकार के साथ इसी तरह चर नाम है और उनके लिए गेटर और setters होना आवश्यक है।

अब और अधिक कार्यक्षमताओं को जोड़ा गया है। आप एक इकाई डेटा को अपने बीन में भी कॉपी कर सकते हैं। यदि किसी इकाई में इसमें कोई अन्य इकाई है तो आप आंतरिक इकाई के रनटाइम परिवर्तन के लिए संबंधित विकल्प से संबंधित विकल्प को पास कर सकते हैं।

ईजी।

ParentEntity parentEntityObject = getParentDataFromDB(); 
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>(); 
map.put(InnerBean1.class, InnerEntity1.class); 
map.put(InnerBean2.class, InnerEntity2.class); 
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map); 

यह स्थिति बहुत उपयोगी है जब आपकी संस्थाओं में संबंध होता है।

0

आप इसे जावा प्रतिबिंब API का उपयोग करके प्राप्त कर सकते हैं।

public static <T> void copy(T target, T source) throws Exception { 
    Class<?> clazz = source.getClass(); 

    for (Field field : clazz.getDeclaredFields()) { 
     if (Modifier.isPrivate(field.getModifiers())) 
      field.setAccessible(true); 
     Object value = field.get(source); 
     field.set(target, value); 
    } 
} 
संबंधित मुद्दे

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