EJB 3.0(Public Draft)入門記 Java Persistence API Chapter3 その1

今日からChapter 3です。


Chapter 3 Entity Operation

Chapter3ではEntityMangerインタフェースとQueryインタフェースを扱うそうです。


3.1 EntityManager

persistence context と persistence unit という新しい概念が出てきます。ざっと見てみます。英語難しいなぁ。自信なし。

  • persistence context
    • 一意性をもつエンティティのインスタンスの集合。persistence context内ではエンティティのインスタンスやライフサイクルが管理される。
  • persistence unit
    • アプリケーションによって分類されるクラスの集合を定義したもの。これらのクラスは単一のデータベースにいっしょにマップされなければいけない。

上の定義を踏まえたうえでEntityManagerについて見てみます。EntityManagerはpersistence contextと関連があり、EntityManagerのインタフェースにはpersistence contextとやりとりするためのメソッドが定義されているそうです。要するにEntityManagerを介して永続的なエンティティを生成したり、削除したり、プライマリキーで取得したり、検索したりするできるということです。EntityManagerはChapter1や2で少し使いました。あるEntityMangerのインスタンスによって管理されるエンティティの集合はpersistence unitによって定義されるそうです。

persistence contextとpersistence unitのちがいがうまくのみこめないです...。とりあえず、persistence contextはエンティティを管理して、persistence unitはエンティティの集合を定義する、と覚えておきます。
persistence contextについてはChapter 3、Entity Managerとpersistence unitの関連はChapter 6で扱うらしいです。


3.1.1 EntityManager Interface

EntityManagerのInterfaceの定義が載っています。こんな感じらしいです。なんとなーくですがメソッド名からイメージつかめそうなので、とりあえずJavaDocコメントは省きました。主要なものは3.2節で詳しくのべられているようです。

public interface EntityManager {
	public void persist(Object entity);
	public  T merge(T entity);
	public void remove(Object entity);
	public  T find(Class entityClass, Object primaryKey);
	public  T getReference(Class entityClass, Object primaryKey);
	public void flush();
	public void refresh(Object entity);
	public boolean contains(Object entity);
	public Query createQuery(String ejbqlString);
	public Query createNamedQuery(String name);
	public Query createNativeQuery(String sqlString);
	public Query createNativeQuery(String sqlString, Class resultClass);
	public Query createNativeQuery(String sqlString, String resultSetMapping);
	public void close();
	public boolean isOpen();
	public EntityTransaction getTransaction();
}

EntityManagerのInterfaceについて次の規則があるそうです。

  • persist、merge、remove、flush、refreshのメソッドはトランザクションコンテキスト内で呼び出される必要がある。トランザクションコンテキストがない場合、javax.persistence.TransactionRequiredExceptionがスローされる。
  • createQuery、createNamedQuery、createNativeQueryのメソッドに対する引数が妥当なクエリ文字列でなかったり妥当な結果セットを要求するものでない場合、IllegalArgumentExceptionがスローされるかクエリの実行が失敗する。
  • EntityManagerインタフェースのメソッドで実行時例外がスローされるとトランザクションロールバックされる。
  • close、isOpne、getTransactionのメソッドはアプリケーション管理のエンティティマネジャーとエンティティマネジャーのライフサイクルを管理するために使われる。


3.1.2 Example of Use of EntityManager API

例を写してみます。

@Stateless
public class OrderEntry {
  @PersistenceContext
  EntityManager em;
  
  public void enterOrder(int custID, Order newOrder) {
    Customer cust = (Customer)em.find("Customer", custID);
    cust.getOrders().add(newOrder);
    newOrder.setCustomer(cust);
  }  
}

そういえばEnitityManagerのDIにはPersistenceContextアノテーション使うんだった(何回か使った割には意識していなかった)。persistence contextの概念の理解が甘いためですが、EnitityManagerのDIがPersistenceContextアノテーションで行われることがしっくりこないです。EnitityManagerアノテーション(そんなのないけど)でいいじゃんみたいな。
findメソッドの第一引数は文字列でもOKなんですね。いままでClassしか渡したことなかったです。
追記 この例、おかしいです。findメソッドの第一引数にStringは渡せないですね。