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コンテナと統合されたサードーパーティというとHibernateTopLinkのことですね。JSE環境で言えばたとえばSeasarKuinaがpersistence provider runtimeに相当するといえるんでしょうか。

永続性プロバイダランタイムによるEntityのステートへのアクセスについて3点述べられています。

昨日(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マッピングメタデータのオーバーライドはお勧めしないとあります。

エンティティの永続的なフィールドやプロパティに認められる型が挙げられています。箇条書きします。

  • 各種primitive型
  • java.lang.String
  • serializableな型
  • enum
  • エンティティやエンティティのコレクション
  • 組み込み(embeddable)クラス

配列は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 Collection orders = 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の要件を書いときます。

こんなものかな?まだ動かせるほどわかってないので今回はこれで終わり。次回は 2.1.3 Entity Instance Creationからです。