2009-05-07 18 views
14

私は同じPOJOクラスの別のインスタンスにプロパティをコピーする単純なJava POJOを持っています。Java Beanのプロパティを別のJava Beanにコピーする方法は?

私はBeanUtils.copyProperties()でそれを行うことができますが、サードパーティライブラリの使用を避けたいと思います。

だから、それをどうやって行うのが適切で安全な方法ですか?ところで

は、私は、Java 6に

+8

Um、BeanUtils.copyProperties()*は適切な方法です。そのライブラリには、それ以外の方法で簡単に行う方法がないため、そのライブラリにあります。 本当にBeanUtilsを使いたくない場合は、ソースコードをダウンロードしてメソッドをコピーしてください。 – skaffman

+1

skaffman - 私は私の答えを投稿したとき、あなたのコメントが表示されませんでした、ごめんなさい。しかし、あなたが見ることができるように、私は完全にあなたに同意します:) – MetroidFan2002

+1

Springには[BeanUtils.copyProperties](http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans /BeanUtils.html)メソッドは、既にSpringを使用している方が便利です。 – pimlottc

答えて

12

を使用している私は、あなたが々BeanUtilsのソースコードを見れば、それが実際々BeanUtilsを使用せずにこれを行う方法を紹介しますね。

単純にPOJOのコピーを作成したい場合(あるPOJOから別のPOJOにプロパティをコピーするのと全く同じ)、clone()メソッドとCloneableインターフェイスを実装するようにソースBeanを変更できます。

+1

すべてのプロパティがフィールドでサポートされている場合、クローン可能にするとうまくいくはずです。非常に効率的です。ただし、それは浅いコピーであることに注意してください。 –

+1

Cloneableとオーバーライドclone()を実装して親の実装を呼び出すためには、それは浅いコピーです。もちろん、深いコピーを作成するなど、何かを行うためにclone()を実装することもできます。 clone()の詳細については、「有効なJava」を参照してください。 –

2

JavaBeans API、特にIntrospectorクラスをご覧ください。 BeanInfoメタデータをgetsetのプロパティに使用できます。 JavaBeans specificationをまだ読んでいない場合は、それを読むことをお勧めします。また、reflection APIに慣れ親しむことができます。

+0

良いアドバイスだが、おそらくBeanUtils.copyProperties()の実装が劣悪になるすべての最終結果を想定するのは公正だろう。 –

+0

これは公正なコメントだが、何が起こっているのか分からない。 – McDowell

+0

Thx。私はJava 6で新しくなったので、以前のバージョンよりも簡単に行う方法があることを願っています。しかし、私は間違いなくあなたのリンクを見ていきます。 – paulgreg

1

ここでです。簡単な方法はありません。 IntrospectorとJava Beanライブラリはモノリシックです - BeanUtilsはこれを囲む単純なラッパーであり、うまく機能します。ライブラリを持たないライブラリを持たないのは一般的には悪い考えです。まず、Javaに存在するはずの一般的な機能はありますが、そうではない共通の理由があります。

10

Google App Engine用のアプリケーションを開発しているときに同じ問題がありました。ここでは、Commons Loggingの制限によりBeanUtilsを使用できませんでした。とにかく、私はこの解決策を思いついて、うまく働いた。

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-silently私はあなたが読み取り専用プロパティのサポートを追加することをお勧めします 'propertyDescriptor.getWriteMethod () 'はnullを返します。 – 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

Heyの友人は、作成したReflectionUtilクラスを使用して、1つのBean値を別の同様のBeanにコピーします。 このクラスはCollectionsオブジェクトもコピーします。
https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java

注:このBeanはタイプと同様の変数名を持っており、彼らのためにゲッターとセッターを持っている必要があります。

さらに多くの機能が追加されました。 1つのエンティティデータをそのBeanにコピーすることもできます。 あるエンティティに別のエンティティがある場合、内部エンティティの実行時変更に関連するBeanにmapオプションを渡すことができます。

例:あなたのエンティティの関係が含まれている場合

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

Java Reflection 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); 
    } 
} 
関連する問題