web-dev-qa-db-ja.com

あるBeanから別のBean(同じクラスではない)にプロパティを再帰的にコピーします(ネストされたBeanを含む)

あるBeanから別のBeanへのディープコピーを実現するために必要な独自のコードの量が最も少ないアプローチはどれですか?目標は、ソースプロパティとターゲットプロパティが名前で一致したときに自動的にそれを行うことです。

ソースメインBean:

public class SourceBean {
    private String beanField;
    private SourceNestedBean nestedBean;

    // getters and setters
}

ソースネストされたBean:

public class SourceNestedBean {
    private String nestedBeanField;

    // getters and setters
}

ターゲットメインBean:

public class TargetBean {
    private String beanField;
    private TargetNestedBean nestedBean;

    // getters and setters        
}

ネストされたBeanのターゲット:

public class TargetNestedBean {
    private String nestedBeanField;

    // getters and setters
}


使用例: Spring BeanUtils.copyProperites() 1行のコードでSourceBeanからTargetBeanへの浅いコピーを作成できましたが、ネストされたBeanはコピーされません。 できるだけ独自のコードを記述せずに(ほぼ同じ)ディープコピーを実行できる成熟したユーティリティ(必ずしもSpring Frameworkである必要はありません)はありますか? BeanUtils.copyProperties())?

9
Sergey Pauk

これを行う1つの方法は、 Jackson ObjectMapper を使用し、 convertValue()メソッド を使用することです。

_ObjectMapper mapper = new ObjectMapper();
SourceBean source = ...;
TargetBean target = mapper.convertValue(source, TargetBean.class);
_

convertValue()は、ジェネリック型でも機能するようにオーバーロードされていることに注意してください。また、SourceBeanがTargetBeanに割り当て可能である場合など、状況によってはconvertValue()が指定された値を返すことに注意してください。

JacksonはJSONのシリアル化/逆シリアル化ライブラリであるため、convertValue()は、メモリ内のJSONにsourceをシリアル化し、このJSONをTargetBeanのインスタンスに逆シリアル化します。したがって、高いパフォーマンスは期待できません。ただし、変換は1行のコードで実行されます。

パフォーマンスが必要な場合は、手動でマッピングを行うのが最善です。それ以上に良いものはありません。

単純さが必要な場合は、上記で説明したようにジャクソンを使用してください。

良いトレードオフは Orika です。これは、反射を使用しない構成がほとんどない高性能マッパーです。

Dozer Mapperを使用して、ディープコピーを実行できます。 http://dozer.sourceforge.net/documentation/deepmapping.html を参照してください。

3

Javaでディープコピーを使用する場合は、ObjectOutputStreamとObjectInputStreamを使用する必要があり、コピーする必要のあるすべてのクラスはSerializableを実装する必要があります。

public Object deepCopy() throws IOException, ClassNotFoundException{
    //store object in memory using serial
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
}
0
whjlou