EJB 3.0(Public Draft)入門記 Chapter 5 その2

今回はEntityManagerの取得方法についてです。いままで@PersistenceContextで取得していましたが、ほかにも方法があるようです。

5.2 Obtaining an EntityManager

エンティティマネジャーをコンテナ管理とするかアプリケーション管理とするかで取得方法が異なります。複数の永続アーカイブが存在する場合、アプリケーションはどの永続ユニットを使用するのか指定しなければいけないそうです。

永続アーカイブ(persistence archive)という言葉がでてきましたが、文脈的に永続ユニットと1対1?僕の感覚では永続アーカイブが物理的なクラスファイルとかjarをまとめたものを指していて永続ユニットが論理的なエンティティを指している感じです。

5.2.1 Obtaining a Container-managed Entity Manager

コンテナ管理のときは次のいずれかでEntity Managerを取得できるとのことです。

  • DI
  • JNDI lookup
  • EntityManagerFactory.getEntityManager()メソッドを呼ぶ

一番使うのはもちろんDIですね。というかあとの2つは使う機会あるのかな?

DIのアノテーションである@PersistenceContextの要素にはunitNameとtypeがあります。

  • unitName : 永続ユニットの名前を指定
  • type : トランザクションスコープの永続コンテキストか拡張永続コンテキストかを指定

http://d.hatena.ne.jp/taedium/comment?date=20051107#cのひがさんのコメントによるとSeasar2ではsetEntityManager(EntityManager em)でDIできるそうです。そのときのunitNameとかtypeとかの指定はdiconで行うことになるのだと思います。


5.2.2 Obtaining a Application-managed Entity Manager

アプリケーション管理の場合は、EntityManagerFactoryインタフェースを使って取得できるようです。

5.2.2.1 Obtaining an Entity Manager Factory in a J2EE Container
J2EEの環境では次の方法でEntityManagerFactoryを取得できるとのことです。

  • DI
  • JNDI lookup

DIには@PersistenceUnitを使います。例を写します。

@PersistenceUnit
EntityManagerFactory emf;

J2EE Container使っていてもEntityManagerのライフサイクルを自分で制御するならばアプリケーション管理と呼ばれるのですね。いつ使うのかなぁと思ったのですがどの永続ユニットを使用するか条件分岐したいときに使うんでしょうか?

5.2.2.2 Obtaining an Entity Manager Factory in a J2SE Environment
J2EEコンテナ外の環境では、javax.persistence.PersistenceがEntityManagerFactoryへのアクセスを可能にしてくれるブートストラップクラスになるようです。

例を写します。

EntityManagerFactory emf = 
  javax.persistence.Persistence.createEntityManagerFactory("Order");
EntityManager em = emf.createEntityManager();

createEntityManagerFactoryメソッドの引数には永続ユニットの名前を渡します。永続ユニットがひとつしかない場合は渡す必要なしです。でも複数あるにもかかわらず、名前を渡さないとPersistenceExceptionが起きるそうです。

5.2.2.3 The EntityManagerFactory Interface
EntityManagerFactoryのインタフェースです。

public interface javax.persistence.EntityManagerFactory {
  EntityManager createEntityManager();
  EntityManager createEntityManager(PersistenceContextType type);
  EntityManager getEntityManager();
  void close();
  public boolean isOpen();
}

JavaDocコメント削ってしまいましたが結構な説明がJavaDocコメントにあります。
重要なのはgetEntityManager()かな?こいつは、JTAに関連付けられたEntityManagerを返してくれるようです。永続コンテキストがなかったら作成してJTAトランザクションに関連付けて返してくれるし、JTAトランザクションに関連付けられた永続コンテキストがすでにあればそいつを返してくれるらしいです。JTAトランザクションがはじまってなければ後にJTAトランザクションに関連付けられるであろうEntityManagerのインスタンスが作成されるようです。

あとclose()はちゃんと呼んでねとのこと。

5.2.2.4 Control of the Application-Managed EntityManager Lifecycle
EntityManger.close()とEntityManger.isOpen()の説明です。

気をつけないといけないのは

  • EntityManger.close()はトランザクションがアクティブのときには呼び出しはいけない
  • EntityManger.close()はエンティティマネジャーをコンテナ管理しているときは呼び出してはいけない

コンテナ管理isOpen()はメソッド名があらわすとおりEntityMangerがopenかどうかを知るためのメソッドです。特に書いてないですが、コンテナ管理のときに呼び出すことはなさそうです。


5.2 Obtaining an EntityManager終わりです。
Chapter 6 とか 7 とかを学んで余裕があればアプリケーション管理のエンティティマネジャーも試しに動かしてみようと思います。