コンテナ管理による永続性(CMP)Entity Beanの使用法

この文書ではWebOTX内でコンテナ管理による永続性(CMP)Entity Beanを動作させる方法についてを説明します。

以下のトピックがあります。

CMPに関する詳細な仕様はEnterprise JavaBeans Specification, v2.1の10章、11章、14章を参照してください。

WebOTXのCMPサポート

WebOTXのCMPでは以下をサポートしています。

コンテナ管理による永続性(CMP)マッピング

CMPを使用するEntity Beanを実装する場合、CMPフィールドとデータベースのCMRフィールド(リレーション)のマッピングが問題となります。この章ではマッピングに関する以下の項目について説明します。

マッピング配備記述子ファイル

CMP Beanを含んだモジュールには、以下のファイルが含まれている必要があります。

nec-cmp-mappings.xmlファイルはCMPフィールドとデータベースのCMRフィールド(リレーション)をマッピングします。それぞれのCMPに対して、主テーブルが選択される必要があります。そしてオプションとして複数の副テーブルがあります。CMPフィールドは主テーブルまたは副テーブルの列にマッピングされます。CMRフィールドは列リストのペアにマッピングされます。(通常、列リストとは主キーと外部キーのペアに関連付けられた列のリストです)

nec-cmp-mappings.xmlファイルはnec-cmp-mapping_1_1.dtdファイルのフォーマットに従っています。ユーザが定義したBeanクラスと一緒にEJB-JARファイルにパッケージされます。META-INFディレクトリ配下に存在します。

otxadminコマンドや配備ツールを使用して配備を行う場合、nec-cmp-mappings.xmlがすでに存在していなければ、配備中に自動的にnec-cmp-mappings.xmlというファイル名でマッピングを作成します。

nec-cmp-mappings.xmlファイルの自動生成はnec-ejb-jar.xmlファイル中または配備時に指定されるオプションによって動作を変えることができます(自動マッピングオプションを参照してください)。自動マッピングを使用する場合、開発者はJavaプログラミング言語だけを知っていればよく、データベーススキーマのことを理解したり知っていたりする必要はありません。

nec-cmp-mappings.xml配備記述子を直接編集することでEntity Beanのフィールドとリレーションのマッピングを手動で行うこともできます。開発者がXML編集に熟練している場合のみこの方法を取ってください。

CMP配備記述子中のマッピング要素のリストはnec-cmp-mappings.xmlファイルに記述されています。XMLファイルのサンプルはデータベーススキーマ定義のサンプルに記述されています。

マッピング情報はデータベーススキーマファイル(.dbschema)ファイルと連動して作られます。データベーススキーマファイルはBeanが配備されるときに自動的にキャプチャすることができます。(データベーススキーマの自動キャプチャ参照)。また、キャプチャスキーマユーティリティを使用して手動でスキーマを作成することもできます。(キャプチャスキーマユーティリティの使用法参照)。

マッピングの機能

マッピングとはオブジェクト指向モデルデータとリレーショナルモデルデータ(通常はリレーショナルデータベースのスキーマ)を結びつける機能のことです。CMP実装はデータを含み、動作が関連付けられた、相互関係を持つBeanの集合と、スキーマとの結びつけを提供します。これによって開発者はJavaアプリケーションの一部分としてデータベースを表現したオブジェクトを使用できます。開発者は必要に応じて、これらBeanの最適化のためにマッピングをカスタマイズすることもできます。結果、永続的なデータベース情報と通常の一時的なプログラムデータの両方にアクセスすることができる単独データモデルになります。WebOTXによって提供されるマッピングの機能とは以下のとおりです。

自動マッピングのオプション

開発者は自動マッピングを、配備記述子要素やコマンドラインオプションを使うことにより以下のようにコントロールすることができます。

nec-ejb-jar.xmlファイル中のcmp-resource要素の副要素である、以下の選択的データは配備時のデータベースの表自動作成をコントロールします。cmp-resource要素についての詳細はリソースマネージャの設定方法を参照してください。

要素 デフォルト 説明
create-tables-at-deploy false trueの場合、EJBコンテナによって自動的にマッピングされたBeanのためのデータベーステーブルが作成されます。falseの場合、テーブルは作られません。
drop-tables-at-undeploy false trueの場合、Beanの配備解除時、Beanが最後に配備されたときに自動的に作成されたデータベーステーブルが削除されます。falseの場合、テーブルは削除されません。
database-vendor-name なし テーブルを作成するデータベースベンダの名前を指定します。指定できる値はdb2、derby、mssql、oracle、sybaseです。大文字小文字は区別されません。値が指定されなければ、コネクションはnec-ejb-jar.xmlファイルの中でcmp-resource要素のjndi-name副要素による指定に従って作成されます。そして、データベースベンダ名を読み込みます。コネクションの確立ができない、または値を認識できない場合、SQL-92遵守が仮定されます。
schema-generator-properties なし property副要素によりフィールド指定の型マッピングを指定できます。 またuse-unique-table-namesプロパティを指定することもできます。これがtrueの場合、生成されたテーブル名がそれぞれのアプリケーションサーバドメインの中でユニークであることを意味します。

<schema-generator-properties>
	<property>
		<name>
		Employee.firstName.jdbc-type
		</name>
		<value>char</value>
	</property>
	<property>
		<name>
		Employee.firstName.jdbc-maximum-length
		</name>
		<value>25</value>
	</property>
	<property>
		<name>
		use-unique-table-names
		</name>
		<value>true</value>
	</property>
</schema-generator-properties>

以下のotxadmin deployまたはotxadmin deploydirコマンドのオプションは、配備時のデータベーステーブル自動生成をコントロールします。

オプション デフォルト 説明
--createtables なし trueの場合、Beanが使用するデータベーステーブルを配備時に作成します。falseの場合、テーブルは作られません。指定されない場合、nec-ejb-jar.xmlファイル中のcreate-tables-ant-deploy属性の値が使用されます。
--dropandcreatetables なし trueでかつこのアプリケーションが最後に配備されたときテーブルが自動的に作成されていた場合、最後の配備時に作られたテーブルは削除され、新しいテーブルが作成されます。 trueでかつ最後にこのアプリケーションを配備したとき自動的にテーブルを作成しなかった場合、テーブルの削除は行われません。もし自動的に作成されるものと同じ名前のテーブルが見つかったなら、配備は続行されますが、テーブル作成ができなかったことを警告します。 falseの場合、nec-ejb-jar.xmlファイル中のcreate-tables-at-deployまたはdrop-tables-at-undeployの設定が上書きされます。
--uniquetablenames なし trueの場合、テーブル名がそれぞれのアプリケーションサーバドメインの中でユニークであると指定します。指定されない場合、nec-ejb-jar.xmlファイル中のuse-unique-table-namesプロパティの値が使用されます。
--dbvendorname なし テーブルを作成するデータベースベンダの名前を指定します。指定できる値はdb2、derby、mssql、oracle、sybaseです。大文字小文字は区別されません。指定されなければ、nec-ejb-jar.xmlファイル中のdatabase-vender-name属性の値が使用され、それも指定されなければ、コネクションはnec-ejb-jar.xmlファイルの中でcmp-resource要素のjndi-name副要素による指定に従って作成されます。そして、データベースベンダ名を読み込みます。コネクションの確立ができない、または値を認識できない場合、SQL-92遵守が仮定されます。

モジュール中のBeanの一つ、または複数を手動でマッピングしたうえで、otxadmin deployやotxadmin deploydirのオプションを指定した場合、配備はどの方法でも問題なく行われますが、オプションは無効になり、サーバログに警告が出力されます。

Beanの一つまたは複数のマッピングに配備ツールを使用した場合、otxadmin deployまたはotxadmin deploydir実行時の--uniquetablenamesオプションは無効になります。配備ツールがマッピングを生成した時、テーブル名がユニークであることが保障されます。

otxadmin undeployコマンドの以下のオプションは配備解除時にデータベーステーブルの自動削除をコントロールします。

オプション デフォルト 説明
--droptables なし trueの場合、Beanが配備解除されたとき、そのBeanが最後に配備されたときに自動的に作成されたデータベーステーブルを削除します。falseの場合、テーブルの削除は行いません。 指定されない場合、nec-ejb-jar.xmlファイル中のdrop-tables-at-undeploy属性の値が使用されます。

otxadmin deploy, otxadmin deploydir, otxadmin undeployについて詳しくは、otxadminコマンドリファレンスを参照してください。

コマンドラインとnec-ejb-jar.xmlオプション両方が指定されたとき、otxadminオプションの方が優先されます。

マッピングでサポートしているデータ型

CMPはJavaデータフィールドからSQL型へのマッピングに使用されるJDBCのデータ型をサポートします。サポートされるJDBCデータ型は以下のとおりです。

以下の表は推奨されたJavaの型とJDBC型のマッピングを示します。

Java型 JDBC型 nullを許容するか
boolean BIT No
java.lang.Boolean BIT Yes
byte TINYINT No
java.lang.Byte TINYINT Yes
double DOUBLE No
java.lang.Double DOUBLE Yes
float REAL No
java.lang.Float REAL Yes
int INTEGER No
java.lang.Integer INTEGER Yes
long BIGINT No
java.lang.Long BIGINT Yes
short SMALLINT No
java.lang.Short SMALLINT Yes
java.math.BigDecimal DECIMAL Yes
java.math.BigInteger DECIMAL Yes
char CHAR No
java.lang.char CHAR Yes
java.lang.StringBuffer VARCHAR Yes
java.lang.String VARCHAR Yes
java.lang.String CLOB Yes
Serializable BLOB Yes
byte[] BLOB Yes
java.util.Date TIMESTAMP Yes
java.sql.Time TIME Yes
java.sql.Date DATE Yes
java.sql.Timestamp TIMESTAMP Yes

注意:CMPフィールドにアサインされるJava型はJavaプリミティブ型、Java Serializable型、java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestampに制限されます。Entity Beanのローカルインタフェース型(またはそれのコレクション)はCMRフィールドの型にすることが可能です。

以下の表はデータベースベンダの特定の型へのJDBCタイプの推奨されたマッピングを示しています。

JDBC型 Oracle DB2 Derby Sybase ASE 12.5 MS-SQL Server
BIT SMALLINT SMALLINT SMALLINT BIT BIT
BOOLEAN SMALLINT SMALLINT SMALLINT TINYINT BIT
TINYINT SMALLINT SMALLINT SMALLINT TINYINT TINYINT
SMALLINT SMALLINT SMALLINT SMALLINT SMALLINT SMALLINT
INTEGER INTEGER INTEGER INTEGER INTEGER INT
BIGINT NUMBER BIGINT BIGINT NUMERIC DECIMAL
REAL REAL REAL REAL REAL REAL
FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT
DOUBLE DOUBLE DOUBLE DOUBLE PRECISION DOUBLE PRECISION DOUBLE PRECISION
NUMERIC(p,s) NUMBER(p,s) DECIMAL(p,s) NUMERIC(p,s) NUMERIC(p,s) NUMERIC(p,s)
DECIMAL(p,s) NUMBER(p,s) DECIMAL(p,s) DECIMAL(p,s) DECIMAL(p,s) DECIMAL(p,s)
VARCHAR VARCHAR2 VARCHAR VARCHAR VARCHAR VARCHAR
DATE DATE DATE DATE DATETIME, SMALLDATETIME DATETIME, SMALLDATETIME
TIME DATE TIME TIME DATETIME, SMALLDATETIME DATETIME, SMALLDATETIME
TIMESTAMP TIMESTAMP TIMESTAMP TIMESTAMP DATETIME DATETIME
BLOB BLOB BLOB BLOB IMAGE IMAGE
CLOB CLOB CLOB CLOB TEXT TEXT

注意:上記の表のマッピングは提案であり、サポートするものではありません。これらマッピングがうまく機能しない場合、使用しているデータベースとJDBCドライバのドキュメントを参照してください。

BLOBサポート

Binary Large Object(BLOB)は複雑なオブジェクトフィールドを保存し、検索するのに使用するデータ型です。BLOBは画像のようなバイナリかSerializableオブジェクトで、CMPフィールドにシリアライズ(直列化)されるとき巨大なバイト配列に変換されます。

CMPフィールドがSerializableとして定義されている場合、データベースに保存される前にbyte[]にシリアライズされます。同様に、データベースから値をフェッチするとき、デシリアライズされます。しかし、CMPフィールドがbyte[]として定義されるなら、シリアライズ、デシリアライズは行われず、直接保存またはフェッチされます。

WebOTX環境においてBLOBサポートを有効にする為に、CMPフィールドの型をbyte[]かjava.io.Serializableインタフェースを実装したユーザ定義型に定義してください。CMP Beanをすでに存在するデータベーススキーマにマッピングするなら、フィールドをBLOBタイプのカラムへマッピングしてください。

自動マッピングを使用する場合、開発者はnec-ejb-jar.xmlファイル中のschema-generator-properties要素を使って生成されたスキーマのために、デフォルトのBLOBカラム長を変更する必要がある可能性があります。使用するデータベースベンダのドキュメントを参照し、長さを指定する必要があるかどうかを確認してください。

<schema-generator-properties>
	<property>
		<name>Employee.voiceGreeting.jdbc-type</name>
		<value>BLOB</value>
	</property>
	<property>
		<name>Employee.voiceGreeting.jdbc-maximum-length</name>
		<value>10240</value>
	</property>
...
</schema-generator-properties>

CLOBサポート

Character Large Object(CLOB)は非常に長いテキストフィールドを保存し、検索するのに使われるデータ型です。CLOBは長い文字列に変換されます。

WebOTX環境でCLOBサポートを有効にするには、java.lang.String型のCMPフィールドを定義してください。CMP Beanを既存のデータベーススキーマにマッピングする場合、そのフィールドをCLOB型のカラムにマッピングしてください。

自動マッピングを使用する場合、生成されたスキーマのためにnec-ejb-jar.xmlのschema-generator-properties要素を使用します。デフォルトCLOBカラム長を変える必要がある可能性があります。 データベースベンダのドキュメントを参照し、長さの指定が必要であるか決定してください。

<schema-generator-properties>
	<property>
		<name>Employee.resume.jdbc-type</name>
		<value>CLOB</value>
	</property>
	<property>
		<name>Employee.resume.jdbc-maximum-length</name>
		<value>10240</value>
	</property>
	...
</schema-generator-properties>

データベーススキーマの自動キャプチャ

CMP Beanに対して配備ツールまたはotxadminコマンドによる配備を行うときに、自動的にデータベースのメタデータをキャプチャし、.dbschemaファイルで保存して設定することができます。

nec-cmp-mappings.xmlファイルが<schema/>空エントリを含んでいる場合、nec-ejb-jar.xmlファイル中のcmp-resourceエントリがデータベースとのコネクションを得るのに使用されます、そして、スキーマの自動生成が実行されます。nec-cmp-mappings.xmlファイルが自動生成されるとき、デフォルトで<schema/>エントリを含んでいます。 データベーステーブル構造を変えるなら、CMPフィールドとリレーションの自動的再マッピングのためにBeanを再配備しなければなりません。

キャプチャスキーマユーティリティの使用法

手動でデータベースメタデータ(.dbschema)ファイルを生成するためにはキャプチャスキーマコマンドを使用します。

注意: キャプチャスキーマコマンドを実行するOracleデータベースのユーザがそのスキーマを所有していなければ、ANALYZE ANY TABLE特権を必要とします。これらの特権はデータベース管理者によってユーザに与えられます。 キャプチャスキーマユーティリティはテーブルを変更することはありません。 唯一の目的はデータベース(スキーマ)の構造に関する情報を永続化エンジンに提供することです。 .dbschemaファイルの名前はドメイン内のすべての配備されたモジュールに対して一意でなければなりません。

書式

capture-schema -username name -password password -dburl url -driver jdbcdriver -out filename [-schemaname schemaname] [-table tablename]*

-username name
データベースへのアクセスが承認されているユーザ名を指定します。
-password password
選択されたデータベースへのアクセスのためのパスワードを指定します。
-dburl url
データベースにアクセスする為のドライバのJDBC URLを指定します。
-driver jdbcdriver
JDBCドライバのクラス名を指定してください。このクラスはCLASSPATHに指定されている必要があります。
-out filename
出力する対象を指定します。出力ファイル名に拡張子がない場合、.dbschemaが付けられます。出力ファイル名が.dbschema以外の拡張子である場合、指定された拡張子に加え.dbschemaが付けられ、警告が表示されます。 CMPマッピングのために、-outパラメータはnec-cmp-mappings.xmlファイル中のnec-cmp-mapping要素のschema副要素に相互関連します。このxml中では、出力ファイル名は.dbschemaサフィックスを付けない文字列を指定します。

<schema>RosterSchema</schema>
-schemaname schemaname:
キャプチャされるユーザスキーマの名前を指定します。指定されない場合、デフォルトでユーザがアクセスできるすべてのスキーマから全テーブルのメタデータをキャプチャします。

注意:ユーザが複数のスキーマにアクセス可能である場合、このパラメータが未指定の時同じ名前の複数のテーブルがキャプチャされることを意味します。

-table tablename
テーブル名を指定します。複数回このパラメータを使用することにより、複数のテーブルに対するメタデータをキャプチャすることができます。指定されない場合、データベーススキーマ中のすべてのテーブルがキャプチャされます。

capture-schema -dburl jdbc:oracle:thin:@localhost:1521:orcl -username scott -password tiger -driver oracle.jdbc.driver.OracleDriver -out RosterSchema.dbschema

リソースマネージャの設定方法

リソースマネージャはCMP実装であるPersistenceManagerFactoryによって使用されています。 「統合運用管理ツール」を使用して設定します。

ドメインツリーから、「リソース」−「永続化リソース」を選択し、右クリックメニューから「永続化リソースの登録」を実行してください。 ここで入力したリソースのJNDI名はnec-ejb-jar.xmlのcmp-resource要素の副要素のjndi-nameに指定されます。

EJB 1.1ファインダークエリ設定方法

このセクションは以下のトピックを含んでいます。

JDOQLクエリについて

EJB仕様v1.1では、ファインダーメソッド記述フォーマットは指定されていませんでした。WebOTXではファインダーおよびセレクタメソッド実装のためにJava Data Objects Query Language(JDOQL)クエリの拡張を使用します。EJB2.1ではコンテナは自動的にEJBQLクエリからJDOQLにマッピングされます。EJB1.1では、このマッピングは開発者が行っていました。基本的なJDOQLクエリの以下の要素を指定することができます。

WebOTX固有の配備記述子(nec-ejb-jar.xml)はEJB1.1ファインダーメソッド設定へ以下の要素の保存を提供します。

WebOTXはEJB1.1Entity BeanのJDOQLクエリを構成します。開発者がJDOQLクエリによって指定することにより、フィルタ、パラメータ宣言、変数宣言の追加および並び替えが行われます。ファインダーメソッドパラメタを使用することでクエリが実行されます。JDOQLクエリリザルトセットからのオブジェクトはEJB1.1ejbFindメソッドで返却される主キーのインスタンスに変換されます。

JDO仕様(JSR12を見てください)はJDOQLの包括的な記述を提供します。 以下の情報はEJB1.1ファインダーを定義するのに使用される要素を要約しています。

クエリフィルタ式

フィルタ式は候補のクラスの各インスタンスのために評価されたboolean式を含むStringです。フィルタが指定されなければ、デフォルト値はtrueになります。有効な式を構成するための規則はJava言語に従いますが以下の違いがあります。

ノート:浮動小数点値同士の比較は不正確なものとなります。それゆえ浮動小数点値との等価比較(==,!=)は注意して使う必要があります。式における識別子は宣言しているパラメータと変数に加え、候補のクラスの名前空間にあると考えられます。 Java言語のように、これは、予約語であり、評価される現在のインスタンスを参照します。

以下の式はサポートされています。

クエリパラメータ

パラメータ宣言はカンマで区切られた一つあるいは複数の型宣言子を含むStringです。これはメソッドのシグネチャのためのJava文法に従います。

クエリ変数

型の宣言はローカル変数宣言のJava文法に従います。

例1

以下のクエリはMichaelと呼ばれるすべてのプレイヤーに返却します。nameフィールドと文字列リテラルを比較するフィルタを定義します。

name == "Michael"

nec-ejb-jar.xmlファイルのfinder要素はこのようになります。

<finder>
	<method-name>findPlayerByName</method-name>
	<query-filter>name == "Michael"</query-filter>
</finder>

例2

このクエリは指定されたpriceの範囲のすべての製品を返却します。priceの上限と下限の二つのパラメータを定義します。つまりdouble lowとdouble highになります。フィルタは二つのクエリパラメータとpriceフィールドを比較します。

low < price && price < high

Query orderingは price ascendingにセットします。

nec-ejb-jar.xmlファイルのfinder要素は次のようになります。

<finder>
	<method-name>findInRange</method-name>
	<query-params>double low, double high</query-params>
	<query-filter>low &lt; price &amp;&amp; price &lt; high</query-filter>
	<query-ordering>price ascending</query-ordering>
</finder>

例3

このクエリは指定したnameを持つプレイヤーよりも、高いsalaryのプレイヤーをすべて返却します。nameのクエリパラメータをjava.lang.String nameと定義します。その上で、プレイヤーが比較する変数を定義します。Beanに対応した永続化可能クラスの型があります。

mypackage.PlayerEJB_170160966_JDOState player

フィルタは指定されたnameのプレイヤーのsalaryとこのキーワードによって指示された現在のプレイヤーのsalaryを比較します:

(this.salary > player.salary) && (player.name == name)

nec-ejb-jar.xmlファイルのfinder要素は以下のようになります。

<finder>
	<method-name>findByHigherSalary</method-name>
	<query-params>java.lang.String name</query-params>
	<query-filter>
	(this.salary &gt; player.salary) &amp;&amp; (player.name == name)
	</query-filter>
	<query-variables>mypackage.PlayerEJB_170160966_JDOState player</query-variables>
</finder>

CMPの最適化

このセクションではCMP Entity Beanを使用する際の最適化方法について論じます。

フィールドステートのローディング

デフォルトでは、抽象的BeanのejbLoadメソッドを呼び出す前に、EJBコンテナはすべてのCMPフィールド(ただし、BLOBとCLOBフィールドは除く)のステートをロードします。 このアプローチは巨大なステートを持ったエンティティオブジェクトにとって、大部分のビジネスメソッドがステートの一部だけとアクセスする場合、最適ではないかもしれません。 これが問題になるようならば、あまり頻繁に使われないフィールドのためにnec-cmp-mapping.xmlのfetched-with要素を使用してください。