去年、Java EE6でWebプロトを作成していた頃に、JPAのEntityをディープコピーする方法に触れました。→Challenge Java EE 2012/10/30記事 ディープコピー in JPA
この当時やった方法は、StackOverflowの元ネタを参考に、コピーしたいEntityをfindで一旦取ってきてdetachし、IDを塗り替えて保存するという、今思うと結構ムチャクチャなやり方…(^^;
今の開発でこの方式を踏襲しようとしたのですが、試験しなおしてみると色々と問題があったので、トリッキーなやり方は止めて、普通にディープコピーすることにしました。
(もし参考にして実装された方がいたら申し訳ないです…うまくいっていることを祈ります;)
ディープコピーは、自前で実装もあると思うのですが、Entityの階層もそこそこに深いので、手間だな…とライブラリを探しました。
なんかJavaでディープコピー、シャローコピーするライブラリはたくさんありすぎて、どれがどういいのか判断に迷う…(-_-;ここがJavaの苦しい所でもあり、時間があれば楽しい所でもある感じです。
まずはStackOverflowにあった以下記事を参考にしました。
Java: recommended solution for deep cloning/copying an instance
pro/consって何?と思ったら、賛否、って感じの意味なんですね(^^;
Java Deep-Cloning Libraryはリンク切れしてますが、以下にありました。
https://code.google.com/p/cloning/
あと、この記事にないライブラリでもJava Generic Deep Copyとかもありました。
で、あれこれやりながら、最終的にはDozerなるライブラリを選びました。
以下、メモです。
pom.xmlに
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
</dependency>
と追加して終わりです。
DozerでEntityのディープコピー
コードもシンプルでサンプルレベルなら以下のような記述だけで動きます。
Mapper mapper = new DozerBeanMapper();
HogeEntity copyHoge = mapper.map(originalEntity, HogeEntity.class);
ただ、Mapperのインスタンスはシングルトンが推奨されていたので、そこら辺だけ工夫すればよいかなと。
結構シンプルに実装できました。
ログ注意
実行して、やたらコピー遅いなぁ、と思っていたら、DEBUGレベルで大量のログが出てました(^^;今の開発ではSLF4j&Logbackなので、logback.xmlに
<configuration>
<logger name="org.dozer" level="off" />
</configuration>
という感じで、とりあえず回避しました。
このloggerが全然効かなくてハマってたのですが、pomにlogback-coreがなかったことが駄目だったようで、入れたら効きました。