付録C.2 デプロイメントに関する規約

デプロイメントに関する規約には,コンテナ側の責任とJPAプロバイダ側の責任があります。

<この項の構成>
(1) コンテナ側の責任
(2) JPAプロバイダ側の責任
(3) javax.persistence.spi.PersistenceProviderインタフェース
(4) javax.persistence.spi.PersistenceUnitInfoインタフェース

(1) コンテナ側の責任

デプロイメント時に,コンテナはアプリケーション内の決められた場所にパッケージングされたpersistence.xmlを検索します。アプリケーション内にpersistence.xmlが存在する場合には,コンテナはpersistence.xmlに定義された永続化ユニットの定義を処理します。なお,コンテナが検索する場所については,「5.8 persistence.xmlでの定義」を参照してください。

コンテナはpersistence.xmlファイルをpersistence_1_0.xsdで検証します。検証の結果,エラーが発生した場合にはユーザに通知します。persistence.xmlにプロバイダやデータソースの情報が指定されていない場合には,デフォルト値が使用されます。使用されるデフォルト値については,「5.8 persistence.xmlでの定義」を参照してください。コンテナが永続化ユニットのエンティティマネージャファクトリを作成するときには,JPAプロバイダにプロパティを渡すことがあります。

コンテナは,persistence.xmlで永続化ユニットごとに定義されたjavax.persistence.spi.PersistenceProviderの実装クラスのインスタンスを作成し,createContainerEntityManagerFactoryメソッドを呼び出して,コンテナ管理のエンティティマネージャを作成するためのEntityManagerFactoryを取得します。永続化ユニットのメタデータは,PersistenceUnitInfoオブジェクトとして,createContainerEntityManagerFactoryメソッドの引数でJPAプロバイダに渡されます。コンテナは一つの永続化ユニット定義に対して,一つだけEntityManagerFactoryを作成し,そのEntityManagerFactoryから複数のEntityManagerを作成します。

永続化ユニットが再デプロイされる場合には,コンテナはすでに取得したEntityManagerFactoryのcloseメソッドを呼び出したあと,createContainerEntityManagerFactoryを新しいPersistenceUnitInfoとともに呼び出します。

(2) JPAプロバイダ側の責任

JPAプロバイダはPersistenceProvider SPIを実装し,PersistenceProviderのcreateContainerEntityManagerFactoryメソッドが呼ばれたときに,引数で渡される永続化ユニットのメタデータ(PersisetnceUnitInfo)を使用して,EntityManagerFactoryを作成し,コンテナに返す必要があります。

JPAプロバイダは,永続化ユニットに含まれるマネージドクラス(エンティティクラスなど)のメタデータアノテーションを処理します。また,永続化ユニットでO/Rマッピングファイルが使用されている場合には,JPAプロバイダが解釈する必要があります。このとき,O/Rマッピングファイルをorm_1_0.xsdを使用して検証し,エラーが発生した場合はユーザに通知する必要があります。

(3) javax.persistence.spi.PersistenceProviderインタフェース

JPAプロバイダは,javax.persistence.spi.PersistenceProviderインタフェースを実装する必要があります。このインタフェースはコンテナによって呼び出されるものであり,アプリケーションから呼び出すものではありません。PersistenceProviderの実装クラスは,publicで引数のないコンストラクタを持っている必要があります。

javax.persistence.spi.PersistenceProviderインタフェースを次に示します。

package javax.persistence.spi;

/**
* JPAプロバイダによって実装されるインタフェースです。
* このインタフェースはEntityManagerFactoryを作成するために使用されます。
* Java EE環境ではコンテナによって呼び出され,
* JavaSE環境ではPersistenceクラスによって呼び出されます。
*/
public interface PersistenceProvider {

 /**
 * PersistenceクラスがEntityManagerFactoryを作成する時に呼び出されます。
 *
 * @param emName 永続化ユニットの名前
 * @param map JPAプロバイダによって使用されるプロパティのMap。
 * ここに指定されたプロパティは,persistence.xmlファイルの対応する
 * プロパティを上書きするため,またはpersistence.xmlファイルに
 * 指定されていないプロパティを指定するために使用されます。
 *(プロパティを指定する必要がない場合はnullが渡されます)
 * @return 永続化ユニットのEntityManagerFactory
 * JPAプロバイダが正しくない場合は,nullを返します。
 */
 public EntityManagerFactory createEntityManagerFactory(String
 emName, Map map);
 
 /**
 * コンテナがEntityManagerFactoryを作成する時に呼びだされます。
 *
 * @param info JPAプロバイダが使用するためのメタデータ
 * @param map JPAプロバイダが使用するためのインテグレーションレベルの
 * プロパティ(指定しない場合はnullが渡されます)
 * @return メタデータで指定された永続化ユニットのEntityManagerFactory
 */
 public EntityManagerFactory createContainerEntityManagerFactory(
 PersistenceUnitInfo info, Map map);
}

(4) javax.persistence.spi.PersistenceUnitInfoインタフェース

javax.persistence.spi.PersistenceUnitInfoインタフェースの定義を次に示します。

import javax.sql.DataSource;
/**
* このインタフェースはコンテナによって実装され,
* EntityManagerFactoryを作成する時にJPAプロバイダに渡されて使用される。
*/
public interface PersistenceUnitInfo {

 /**
 * @return persistence.xmlで定義された永続化ユニット名
 */
 public String getPersistenceUnitName();
 
 /**
 * @return persistence.xmlの<provider>エレメントに定義された,
 * JPAプロバイダ実装クラスの完全修飾クラス名
 */
 public String getPersistenceProviderClassName();
 
 /**
 * @return EntityManagerFactoryによって作成されるEntityManagerの
 * トランザクションのタイプを返す。
 * persistence.xmlのtransaction-type属性に指定されたタイプである。
 */
 public PersistenceUnitTransactionType getTransactionType();
 
 /**
 * @return JPAプロバイダが使用するためのJTAが有効な
 * データソースを返す。
 * persistence.xmlの<jta-data-source>エレメントで指定されたデータソースか,
 * デプロイメント時にコンテナによって決定されたデータソースである。
 */
 public DataSource getJtaDataSource();
 
 /**
 * @return JPAプロバイダがJTAトランザクションの外で
 * データにアクセスするための,JTAが無効なデータソースを返す。
 * persistence.xmlの<non-jta-data-source>エレメントで指定された
 * データソースか,デプロイメント時にコンテナによって決定された
 * データソースである。
 */
 public DataSource getNonJtaDataSource();
 
 /**
 * @return JPAプロバイダがエンティティクラスのマッピングを
 * 決定するためにロードする必要のある,マッピングファイル名のリスト
 * マッピングファイルは,標準的なXML形式のマッピングフォーマット
 * でなければならない。
 * 一意の名前を持ち,アプリケーションのクラスパスからリソースとして
 * ロードできるものでなければならない。
 * それぞれのマッピングファイル名は,persistence.xmlの<mapping-file>タグ
 * に指定されたものである。
 */
 public List<String> getMappingFileNames();
 
 /**
 * JPAプロバイダが,永続化ユニットのマネージドクラスを検索する必要のある,
 * JARファイルまたはJARファイルを展開したディレクトリのURLのリストを返す。
 * それぞれのURLはpersistence.xmlファイルの<jar-file>タグに指定された
 * ものである。
 * URLはJARファイルまたはJARファイルを展開したディレクトリを指す
 * ファイルURLか,またはJARのフォーマットのInputStreamを取得できる
 * そのほかのURL形式である。
 *
 * @return JARファイルまたはディレクトリを指すURLオブジェクトのリスト
 */
 public List<URL> getJarFileUrls();
 
 /**
 * 永続化ユニットルートであるJARファイルまたはディレクトリのURLを返す。
 * (永続化ユニットルートがWEB-INF/classesディレクトリである場合,
 * WEB-INF/classesディレクトリのURLを返す)
 * URLはJARファイルまたはJARファイルを展開したディレクトリを指す
 * ファイルURLか,またはJARのフォーマットのInputStreamを取得できる
 * そのほかのURL形式である。
 *
 * @return JARファイルまたはディレクトリを指すURLオブジェクト
 */
 public URL getPersistenceUnitRootUrl();
 
 /**
 * @return JPAプロバイダがマネージドクラスとして扱わなくてはならない
 * クラス名のリスト。
 * それぞれのクラス名はpersistence.xmlファイルの<class>タグに指定された
 * ものである。
 */
 public List<String> getManagedClassNames();
 
 /**
 * @return 永続化ユニットルートに配置されていて,
 * 明示的にマネージドクラスであると指定されていないクラスを,
 * マネージドクラスとして扱うかどうかを返す。
 * この値は,persistence.xmlファイルの<exclude-unlisted-classes>タグに
 * 指定されたものである。
 */
 public boolean excludeUnlistedClasses();
 
 /**
 * @return Propertiesオブジェクト。
 * それぞれのプロパティはpersistence.xmlファイルの<property>タグに
 * 指定されたものである。
 */
 public Properties getProperties();
 
 /**
 * @return JPAプロバイダがクラスやリソースをロードしたり,
 * URLをオープンしたりするために使用できるClassLoader。
 */
 public ClassLoader getClassLoader();
 
 /**
 * PersistenceUnitInfo.getClassLoaderメソッドによって返されるクラスローダで,
 * 新しいクラスの定義や,クラスの再定義のたびに呼ばれる,
 * JPAプロバイダのトランスフォーマーを登録する。
 * このトランスフォーマーは,PersistenceUnitInfo.getNewTempClassLoaderメソッドで返される
 * クラスローダでロードされるクラスには影響を与えない。
 * クラスローディングのスコープ内で永続化ユニットが幾つ定義されていても,
 * 同じクラスローディングのスコープ内でクラスが変換されるのは一度だけである。
 *
 * @param transformer コンテナがクラスの定義(再定義)時に呼び出す,
 * JPAプロバイダのトランスフォーマー
 */
 public void addTransformer(ClassTransformer transformer);
 
 /**
 * JPAプロバイダが一時的にクラスやリソースをロードしたり,
 * URLをオープンしたりするために使用できるクラスローダの
 * 新しいインスタンスを返す。
 * このクラスローダのスコープやクラスパスは,
 * PersistenceUnitInfo.getClassLoaderで返される
 * クラスローダと完全に同じである。
 * このクラスローダでロードしたクラスが,
 * アプリケーションのコンポーネントから参照できるようになることはない。
 * JPAプロバイダは,createContainerEntityManagerFactoryの
 * 呼び出しの延長でだけ,このクラスローダを使用できる。
 *
 * @return 現在のクラスローダと同じスコープ・クラスパスを持つ一時的な
 * クラスローダ
 */
 public ClassLoader getNewTempClassLoader();

}

参考
アプリケーションサーバでは,永続化ユニットでJTAデータソース,非JTAデータソースが定義されていない場合には,getJtaDataSource()またはgetNonJtaDataSource()はnullを返します。永続化ユニットでJTAデータソース,非JTAデータソースが定義されていない場合とは,次の状態を指します。
  • persistence.xmlで<jta-data-source>,<non-jta-data-source>が省略されていて,かつデフォルト値がシステムプロパティejbserver.jpa.defaultJtaDsName,ejbserver.jpa.defaultNonJtaDsNameで定義されていない場合
  • システムプロパティejbserver.jpa.overrideJtaDsName,ejbserver.jpa.overrideNonJtaDsNameも定義されていない場合