JPAのConverterで独自クラスを扱う
ConverterをOpenJPAで使おうとしましたが,今のOpenJPAのリリースではConverterに対応していませんでした.
ConverterはJPA2.1以降の実装にしか対応していません.HibernateかEclipseLinkでやりましょう.
私はEclipselinkです
さてコンバーターの説明はこちらでご覧ください.
JavaEE 7 JPA 2.1の新機能コンバータ - しんさんの出張所 はてな編
JPA2.1 の Converter を enum + コードファーストで試す - hd 4.0
上記2記事にあるように,JPAでDBに入っているデータと実際にJava上で扱いたいデータ型が異なるときにコンバーターは非常に便利です.
public Hoge{ private Integer fuga; private Integer piyo; // setter, getter省略 public Hoge(String dododo) { if(dododo.length != 2) throw new IllegalArgumentExeption(); this.fuga = //省略 } @Override public String toString() { return this.fuga.toString() + this.piyo.toString(); } }
@Converter public HogeConverter implements AttributeConverter<Hoge, String>{ @Override public String convertToDatabaseAttribute(Hoge hoge) { return hoge.toString(); } @Override public Hoge convertToEntityAttribute(String value) { return new Hoge(value); } }
例えばこんなのを作ってあとはエンティティクラスのご所望のフィールドに@Convert(converter = "name")とするだけで,出し入れの時にConverterを適用してくれるのです.
ところが
Entityクラスのインスタンスに対して
getHoge().setPiyo(2);
とかした後にEntityManager#persistをしてみても,どうもうまくいきません.
newしたオブジェクトだったらpersistすると更新されるようですが,インスタンスの中身を書き換えただけではJPAには変更されたと認識されないようです.
いろいろ調べた結果
Entityクラスの定義で
@Basic @Mutable // <- 重要 private Hoge hoge;
としなければならなかったようです.
@Mutable | EclipseLink 2.4.x Java Persistence API (JPA) Extensions Reference
毎回インスタンスを生成する必要があるものについてはそんなに気にしなくていいのですが,中身が書き換わるMutableな独自クラスを定義する場合はご注意ください.
それにしてもJPAは日本語ドキュメントが少なくて大変だ.