EJB 3.0(Public Draft)入門記 Java Persistence API Chapter2 その2
Chapter2その2です。今回は永続的なフィールドとプロパティについて。
2.1.1 Persistent Field and Properties
エンティティの永続的なステートは永続性プロバイダランタイム(なんのこっちゃ)によりJavaBeansスタイルのアクセッサー経由もしくはインスタンス変数経由でアクセスされるそうです。永続性プロバイダランタイム「persistence provider runtime」とは、永続性の実装の実行環境を意味し、EJBの環境ではEJBコンテナやEJBコンテナと統合されたサードーパーティがそれにあたるそうです。EJBコンテナと統合されたサードーパーティというとHibernateやTopLinkのことですね。JSE環境で言えばたとえばSeasarのKuinaがpersistence provider runtimeに相当するといえるんでしょうか。
永続性プロバイダランタイムによるEntityのステートへのアクセスについて3点述べられています。
- Entityアノテーションの要素にaccess=FIELDとある場合、永続性プロバイダランタイムはインスタンス変数に直接アクセスしTransientアノテーションがつけられていない非Transientなインスタンス変数が永続化される。
- Entityアノテーションの要素にaccess=PROPERTYとある場合もしくは要素accessが指定されていない場合、永続性プロバイダランタイムはアクセッサーを介してプロパティにアクセスしTransientアノテーションがつけられていないプロパティが永続化される。アクセッサーはpublicかprotectedでなければいけない。
- FIELDアクセスが使用される場合、O/Rマッピングのアノテーションはインスタンス変数につけられる。PROPERTYアクセスが使用される場合、O/Rマッピングのアノテーションはgetterにつけられる。
昨日(Chapter2その1)はEntityがClientにアクセスされる際の規約について触れられていましたが、ここではEntityが永続性プロバイダランタイムにアクセスされる際の規約について述べられているようです。Clientのアクセスと実行環境のアクセスは区別されているんですね。Transientアノテーションについては特に説明がないですが、文章からわかるとおりこのアノテーションがついているフィールドは永続化の対象外にするということみたいです。PROPERTYアクセスがDefaultですがアノテーションをつける位置を考えるとFIELDアクセスのほうがコードが見やすいような気がします。SessionBeanもEntityもフィールドにアノテーションつけちゃうのがいいかなぁ、と思いました。
永続的なプロパティが使用されるとき、エンティティクラスはJavaBeansのメソッドの命名規約に従う必要があるそうです。
束なった値からなるフィールドやプロパティはjava.util.Collection系のインタフェースとして定義されなければいけないらしいです。サポートされているのは
Listについて、移植性をもつアプリケーションは永続性のコンテキストをまたがって保持されるような順序を求めてはいけないと但し書きがあります。ただ@OrderByというアノテーションや細工を加えればコンテキストをまたがった順序づけの保持もOKみたい。
アクセッサーメソッドは値を戻したりセットしたりするだけでなくバリデーションなどのビジネスロジックを含んでもいいそうです。ただ、PROPERTYアクセスを選択しているときは永続性ランタイムがビジネスロジックを実行してしまうことになるから気をつけろみたいなことが書いてあります。でもアクセッサーにビジネスロジックって使いますか?僕はやったことないです。
例外についての話がのってます。アクセッサーメソッドにスローされる実行時例外はトランザクションをロールバックするそうです。永続性ランタイムが永続的なステートをロードもしくはストアするときにアクセッサーによってアプリケーション例外がスローされると永続性ランタイムはトランザクションをロールバックし、アプリケーション例外をラップするPersistenceExceptionをスローするそうです。ここでの例外はSimplified APIに出てきたApplicationExceptionアノテーションと絡んだりするのか気になります。関係があっても複雑になるだけのような気もしますが。
エンティティのサブクラスはアクセッサーメソッドをオーバーライドできるけど移植性を考えるとO/Rマッピングのメタデータのオーバーライドはお勧めしないとあります。
エンティティの永続的なフィールドやプロパティに認められる型が挙げられています。箇条書きします。
配列はbyte、Byte、char、Characterの4種類が認められているんですね。組み込みクラスはどんなものか謎ですが、これは2.1.5節で説明されているそうです。デザパタのステートやストラテジのことかも。
「Calenderはマップされる型に対して完全に初期化されなければならない」と脚注にあるのですがこれはよくわかりませんでした。不要な値が不用意に入らないようにclearメソッドをちゃんと呼んどけよみたいな意味でしょうか?
2.1.2 Example
例が載っているので一応写してみます。やっぱVB.NETよりJavaのほうが書きやすいよなぁ(ひとりごと)。@Entity public class Customer implements Serializable { private Long id; private String name; private Address address; private Collectionorders = new HashSet(); private Set phones = new HashSet(); // no-arg constructor public Customer() { } @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @OneToMany public Collection getOrders() { return orders; } public void setOrders(Collection orders) { this.orders = orders; } @ManyToMany public Set getPhones() { return phones; } public void setPhones(Set phones) { this.phones = phones; } // Business method to add a phone number to the customer public void addPhone(PhoneNumber phone) { this.getPhones().add(phone); phone.setCustomer(this); } }
昨日の復習ですが、Entityの要件を書いときます。
- Entityアノテーションをもつ。(access要素がないのでDefaultでPROPERTYアクセス)
- Serializableを実装
- 引数なしのコンストラクタをもつ
- インスタンス変数はpublic以外。
- JavaBeansの規約にのっとった命名規則。
こんなものかな?まだ動かせるほどわかってないので今回はこれで終わり。次回は 2.1.3 Entity Instance Creationからです。