JPA2.1 の Converter を enum + コードファーストで試す

JavaEE 7 JPA 2.1の新機能コンバータ - しんさんの出張所 はてな編 を読んで、これは enum 使うときに便利や!と思ったので試してみました。あと個人的にはコードファースト*1が好きなので、コードファーストで。

・・・というか、ほとんど Mapping enums done right with @Convert in JPA 2.1 に書かれていたので、英語読める人は以下の文章は読み飛ばしてもらっていいですよ・・('A`)

環境

  • eclipselink 2.5.0
  • derby embedded 10.9.1.0

なお、今回は Java EE アプリケーションサーバー上ではなく、 Java SE 環境( Java7 )で確認しています。

手順

前述のしんさん氏のブログに書かれてる通り、以下の手順を行います。

  1. javax.persistence.AttributeConverter の実装クラスで enum と DB フィールドの相互変換を実装
  2. コンバータークラスに @Converter をつけておく
  3. 対応するエンティティのフィールドに @Convertコンバータークラスを指定

こんな感じですね。このへんのアノテーションは eclipselink にも同名のものがあるので注意。 javax.persistence のほうを使いましょう。

コンバーターを設定ファイルで指定する・・・

この状態で実行すると EntityManager のロード時に org.eclipse.persistence.exceptions.ValidationException が発生します。

 The converter class [sample.SampleConverter] specified on the mapping attribute [enumField] from the class [sample.SomeEntity] was not found. Please ensure the converter class name is correct and exists with the persistence unit definition.

設定ファイルでコンバーターを指定してやる必要があるようです。 Java EE アプリケーションサーバーではうまいことスキャンしてくれるようですが、 SE 環境では無理なようです。 META-INF/orm.xml に指定してやると動きました。

persistence.xml でパスを指定します。

<mapping-file>META-INF/orm.xml</mapping-file>

orm.xml は以下の様な感じ。

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm" version="2.1">
    <converter class="sample.SampleConverter"/>
</entity-mappings>

いちいちこんなことすんのか・・。

なお、試した感じ @Converter(autoApply = true) は効いてないっぽいので、エンティティのフィールドに明示的にコンバーターを指定する必要があるっぽいです。これも Java EE アプリケーションサーバーではry

コードファースト

ここまでの設定で、 DB にはちゃんとコンバーターの変換先の型でカラムが作られます。 String だと VARCHAR(255)Integer だと INTEGER になりました。良かった良かった。

ただし enum はデフォルトで数値型としてカラムが作られるようなので、 enumInteger に変換するようにしてたりすると効いてるのかどうなのかわかりにくいので注意が必要です。意図した値が保存されるかちゃんと確認しましょう。

2013-07-01 13:02 追記

GlassFish4 環境で試したところ、上述の orm.xml の設定なしで通りました。 Java SE 環境だと必要なのかもしれません。

※書き忘れてましたがこの記事は Java SE 環境で試したものです(追記済み)・・m(__)m

*1:実行時にエンティティの定義から自動的にテーブル作るやつ。正式にはなんて言うのか知らん。