このセクションでは、各必須 Bean メソッドの背後にある処理とパーシスタンス ロジックについて詳しく説明します。
Bean インスタンスを作成する場合、コンテナでは Bean の ejbCreate
メソッドを呼び出します。ejbCreate
メソッドによって、渡された引数を検証し、Bean 変数を使用して SQL パラメータを置き換える場合は、渡された引数を Bean インスタンス変数にコピーできます。次に、コンテナでは、createSQL
ステートメントを実行します。通常はこの createSQL
ステートメントによってデータベースに行が挿入されます。プライマリ キーを持つ行がすでに存在する場合は、DuplicateKeyException
が返されます。
次に、コンテナでは、Bean の ejbPostCreate
メソッドを呼び出します。
ejbCreate
を呼び出します。
createSQL
ステートメントを実行します。javax.ejb.DuplicateKeyException
が返されます。postCreateSQL
を実行し、ejbPostCreate
メソッドを呼び出します。
公開記述子で Bean 変数を使用して SQL パラメータを置き換える場合は、次の例に示すように、ejbCreate
メソッドによって、渡された引数を使用する Bean フィールドを初期化する必要があります。
public void ejbCreate(int accountId)
throws CreateException, RemoteException { _id = accountId; _value = 0; }
ejipt.createSQL
env-entry には通常、次のようにデータベースに行を追加する INSERT ステートメントが含まれています。
<env-entry>
<env-entry-name>ejipt.createSQL</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>INSERT INTO account (id, value) VALUES (?, ?)</ env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.createSQL.source</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>source1</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.createSQL.params</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>_id, _value</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.createSQL.paramTypes</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>INTEGER, INTEGER</env-entry-value> </env-entry>
Bean メソッドを実行する前に、コンテナでは、loadSQL
ステートメントを実行し、指定されたフィールドにその結果をコピーして、データベースのステートと Bean インスタンスを同期化します。次に、データベースから取得された値に基づいて詳細に初期化を実行できるように、Bean で ejbLoad
メソッドを呼び出します。
メモ
|
ejipt.loadSQL
の値には通常、次のように、Bean インスタンスのデータが格納されている結果セットを返す SELECT ステートメントが含まれています。
<env-entry>
<env-entry-name>ejipt.loadSQL</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>SELECT value FROM account WHERE id = ?</ env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.loadSQL.source</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>source1</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.loadSQL.params</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>_id</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.loadSQL.paramTypes</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>INTEGER</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.loadSQL.fields</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>_value</env-entry-value> </env-entry>
Bean メソッドの終了後に、コンテナでは Bean インスタンスで ejbStore
メソッドを呼び出します。この手順を使用すると、データベースにデータを格納して Bean インスタンスのステートを同期化する前に、Bean によってインスタンスのパラメータ フィールドを準備できます。
JRun では次のようにメソッドとプロパティを追加して、ejbStore
の呼び出しを制御します。
InstanceManager.setDirty(true)
メソッドを呼び出します。
InstanceManager.setDirty(false)
メソッドを呼び出します。ejbStore
の呼び出しを強制するには、Bean の公開記述子の env-entry
要素で ejipt.isAlwaysDirty
プロパティを true
に設定します。
ejipt.storeSQL
の値には通常、次のように、データベースと Bean の現在のステートを同期化する UPDATE ステートメントが含まれています。
<env-entry>
<env-entry-name>ejipt.storeSQL</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>UPDATE account SET value = ?WHERE id = ?</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.storeSQL.source</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>source1</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.storeSQL.params</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>_value, _id</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.storeSQL.paramTypes</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>INTEGER, INTEGER</env-entry-value> </env-entry>
dirty
フラグが設定されていない場合、コンテナでは、表面的な比較によってインスタンスを保存するかどうかを判断します。コンテナは == 演算子を使用してフィールドのステートとキャッシュされているステートを繰り返し比較して、ステートが変化したかどうかを判断します。深いレベルでの変化が起きた場合、Bean メソッド内で dirty
フラグを明示的に true
に設定して、保存を強制しなければなりません。
インスタンスを削除する場合、コンテナでは、インスタンスがデータベースから削除される前に必要なクリーンアップを実行できるように ejbRemove
メソッドを呼び出します。ejbRemove
では、SQL ステートメントで使用するパラメータを設定する必要があります。
ejipt.removeSQL
の値には通常、次のように DELETE
ステートメントが含まれています。
<env-entry>
<env-entry-name>ejipt.removeSQL</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>DELETE FROM account WHERE id = ?</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.removeSQL.source</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>source1</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.removeSQL.params</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>_id</env-entry-value> </env-entry> <env-entry> <env-entry-name>ejipt.removeSQL.paramTypes</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>INTEGER</env-entry-value> </env-entry>
ほとんどのクライアント アプリケーションでは、1 つまたは複数の行を取得し、場合によっては更新することによってデータベースと対話します。行を作成することはほとんどありません。エンティティ Bean には、クライアントが 1 行以上の既存のデータにアクセスできる finder メソッドが実装されています。エンティティ Bean のホーム インターフェイスとその Bean 実装で、finder メソッドをコーディングします。
findBy
Xxx メソッドを指定します。このメソッドは、Bean のリモート インターフェイスへの参照を返すか、あるいはリモート インターフェイス参照の Enumeration
または Collection
を返します。
ejbFindBy
Xxx メソッドがあります。
すべてのエンティティ Bean には、findByPrimaryKey
と ejbFindByPrimaryKey
メソッドのペアが必要です。ただし、CMP を使用するエンティティ Bean の Bean 実装で、ejbFindByPrimaryKey
を実装する必要はありません。ホーム インターフェイスの findByPrimaryKey
を定義し、公開記述子の findByPrimaryKeySQL
env-entry を指定する必要があります。
エンティティ Bean には、プライマリ キー クラス内のメンバのインスタンス変数がすべて含まれている必要があります。プライマリ キー フィールドのほかに、Bean では返される行の追加の列が含まれるインスタンス変数も定義できます。
ejbFindByPrimaryKey
メソッドを呼び出した後、コンテナでは、
findByPrimaryKeySQLenv-entry
によって指定された SQL ステートメントを実行します。最初に、パラメータ引数、またはプロパティで指定されているフィールド、あるいはその両方を SQL ステートメントの各パラメータにマッピングします。ストアド プロシージャを指定した場合は、キーとして渡された値に関連するオブジェクトがデータベースに含まれているかどうかを調べるチェックがストアド プロシージャに含まれている必要があります。データベース内にデータがある場合は、指定されているフィールドに格納した後で、該当する行を 1 つ返す必要があります。この行によって、コンテナでは、プライマリ キー クラスの有効なインスタンスを構築できます。プライマリ キーに渡されたメンバがデータベース内のオブジェクトに関連付けられていない場合、SQL は行を返しません。
コンテナでは、新しく作成されたプライマリ キー インスタンスを取り出し、そのインスタンスのオブジェクト テーブルから適切な EJB オブジェクトを検索します。オブジェクトが見つかった場合、そのオブジェクトをホーム インターフェイスの findByPrimaryKey
メソッドの結果として返します。EJB オブジェクトが見つからなかった場合、このメソッドでは finder 例外が返されます。
CMP の使用時も複数行 finder メソッドを実装できます。finder メソッドごとに、find*SQL
プロパティを指定する必要があります。たとえば、ホーム インターフェイスで定義された findBigAccounts
メソッドがあるとします。
クライアントによってリモート インターフェイスの findBigAccounts
メソッドが呼び出されると、finderSQL
ステートメントと併用する Bean インスタンス内のパラメータを設定するために、コンテナでは、最初に Bean の ejbfindBigAccounts
メソッドを呼び出します。finder メソッドではヌルを返す必要があります。次に、コンテナでは各 finder SQL ステートメントを順番に呼び出します。結果セットが返されるたびに、コンテナでは次の処理が実行されます。
ejipt.findBigAccountsSQL = SELECT id FROM sometable WHERE balance > 1000000
ejipt.findBigAccountsSQL.fields=custId
finder メソッドで基準が設定されている大口預金口座を見つけるために、次の
env-entry を使用します。
ejipt.findBigAccountsSQL = SELECT id FROM sometable WHERE balance >?
ejipt.findBigAccountsSQL.params=criteria ejipt.findBigAccountsSQL.paramTypes=double ejipt.findBigAccountsSQL.fields=custId
プロパティ ファイルでは、プライマリ キーにも含まれている Bean のフィールドに対する結果列からのマッピングを指定する必要があります。結果に基づいてプライマリ キーのコレクションが作成されると、EJB エンジンでは、関連するエンティティ オブジェクト、つまり公開時にリモート インターフェイスから生成された実装クラスのインスタンスの検索や作成に取りかかります。
finder が一覧または Java 2 コレクションのどちらを返すかによって、EJB エンジンでは、エンティティ オブジェクトの一覧から抜き出した Enumeration
と Collection
のいずれかを作成し、それを呼び出し側に返します。