JPA 2 の Entity クラスをかたどるための Metamodel API (Java EE 7)
最近 Java Persistence API (JPA) を使ってみてます。 まだ使いこなせてはないですがなかなかいいですね。 今まで触ったことのある O/R マッパー *1 の設計が嫌いだったので O/R マッパーにはあんまりいい印象持ってなかったんですが、JPA の設計はよく考えられてて良いと思いました。 Java Persistence criteria query が SQL を意識したものになっているのも良い感じです。
JPA のエンティティクラスに対するメタモデル
Metamodel API というのがあることをさっき知ったのでメモ書きしておきます。 JSR-338 (JPA 2.1) には、メタモデルについて次のように書かれていました。
The Java Community Process(SM) Program - communityprocess - final6.2 Metamodel
Java Persistence criteria queries are based on a metamodel of the managed classes of the persistence unit. Static metamodel classes corresponding to the managed classes of the persistence unit can be generated by means of an annotation processor or can be created by the application developer, or the metamodel can be accessed dynamically by use of the
javax.persistence.metamodel.Metamodel
interface. ThegetMetamodel
method of theEntityManagerFactory
orEntityManager
interface can be used to obtain aMetamodel
instance.6.2.1 Static Metamodel Classes
In the typical case, an annotation processor is expected to be used to produce static metamodel classes corresponding to the entities, mapped superclasses, and embeddable classes in the persistence unit. A static metamodel class models the persistent state and relationships of the corresponding managed class. For portability, an annotation processor should generate a canonical metamodel as defined below.
Java Persistence criteria query は persistence unit 中の managed class のメタモデルを使うようになっているわけですね。 で、アノテーションプロセッサによって静的なメタモデルクラスを生成することもできるし、プログラムの実行中に動的にメタモデルを取得することもできるとのこと。 そして、静的なメタモデルクラスを使用することで、強く型付けされたクエリを記述することができます。
静的なメタモデルクラス
上のページに書かれているサンプルコードそのままですが、次のようなエンティティクラスを考えます。
package com.example; ... @Entity public class Pet { @Id protected Long id; protected String name; protected String color; @ManyToOne protected Set<Person> owners; ... }
このエンティティクラスに対応するメタモデルクラスは次のようになります。
package com.example; ... @Static Metamodel(Pet.class) public class Pet_ { public static volatile SingularAttribute<Pet, Long> id; public static volatile SingularAttribute<Pet, String> name; public static volatile SingularAttribute<Pet, String> color; public static volatile SetAttribute<Pet, Person> owners; }
メタモデルクラスを移植可能なものにするため、JPA では canonical metamodel が定義されています。 (Canonical metamodel の条件にあうクラスは、別の JPA 実装でもサポートされることが保証されるという感じ、だと思う。)
Eclipse における静的なメタモデルの生成
Eclipse IDE for Java EE Developers を使っている場合、プロジェクトのプロパティを変更することで canonical metamodel を自動生成させることができます。 プロジェクトの Facets に JPA を追加している状態だと、プロジェクトのプロパティに 「JPA」 が表示されているはずです。
下の方に 「Canonical metamodel」 ってのがあるので、そこで出力先 (?) ソースフォルダを選択すれば静的なメタモデルクラスが生成されるようになります。
Gradle 使用
Gradle を使ってビルドする場合は、次の記事を参考に Annotation Processing させれば良さそうです。
参考文献、関連記事
- The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 338: JPA 2.1 仕様
- はじめての Java Persistence API | 寺田 佳央 - Yoshio Terada
- http://docs.oracle.com/javaee/7/tutorial/doc/partpersist.htm: Oracle の公式ガイド
- UserGuide/JPA/Using the Canonical Model Generator (ELUG) - Eclipsepedia: EclipseLink (JPA 実装の 1 つ) でメタモデルクラスを生成する方法のドキュメント
- Chapter 4. Metamodel: Hibernate (JPA 実装の 1 つ) のドキュメント
- eclipseでJPAのメタモデルを自動生成する設定 - じゃばらの手記
*1:RoR の ActiveRecord など、主に Active Record パターンのもの。 JPA は Data Mapper パターン。