Primary Keyクラスは、Entity Beanのインスタンスの識別子となるクラスで、特定のインスタンスを検索するのに使用されます。
EJBコンテナは、データベースから取得したプライマリキーに対応するインスタンスを、キャッシュします。
finderメソッドが実行された場合には、equalsメソッドとhashcodeメソッドを使用して、同じプライマリキーのインスタンスがキャッシュされているかを判定して、プライマリキーが合致する場合には、キャッシュされているEJB objectを返却します。
Interstage Studioを使用している場合は、自動的に生成されます。
Primary Keyクラスの規約
Primary Keyクラスは以下の規約を満たしていなければなりません。
java.io.Serializableインタフェースを実装した非リモートJavaオブジェクトでなければなりません。
パラメタなしの空コンストラクタを用意しなければなりません。
ObjectクラスのhashCodeメソッドとequalsメソッドを再定義しなければなりません。
記述する処理
プライマリキー値を格納する変数を記述します。複数記述することもできます。
パラメタなしの空コンストラクタを記述します。
equalsメソッドを記述します。引数で渡されるプライマリキーオブジェクトと同じものかどうか判定します。
hashCodeメソッドを記述します。プライマリキー値のhashcodeを返却します。
equalsメソッドとhashcodeメソッド
equalsメソッドとhashcodeメソッドには以下のような特徴があります。
equalsメソッド
コンテナがインスタンスを検索する際に、プライマリキーの値が同一かを判断するために実行します。
また、EJBObjectクラスのisIdenticalメソッドを実行した際に実行されます。
hashcodeメソッド
equalsメソッドを実行する前に、インスタンスの絞り込みを行うためのメソッドです。異なるインスタンスに対してできるだけ異なる値を返却するようにhashcodeメソッドを定義しておくと、コンテナがインスタンスを検索する際の性能を向上できます。
注意
メソッド定義時の注意事項
equalsメソッドで同じインスタンスと判断される場合は、hashcodeメソッドで同じ整数値を返却するように定義してください。
また、equalsメソッドで同じインスタンスと判断されない場合でも、hashcodeメソッドが異なる整数値を返却する必要はありません。
メソッド定義を誤った場合、CMFの更新処理が反映されないなどの現象が発生する場合がありますので、基本的にはInterstage Studioが出力するひな形を使用してください。
プライマリキーに固定長文字列のDBカラムを指定した場合、データベースから取得されるデータは文字列長分だけ後方空白が補完されて取得されます。
同じキー項目かどうかをequalsメソッドとhashcodeメソッドで判定する際に、これらのメソッドが、補完された後方空白を考慮(後方空白は無視)して実装しないとキー項目を異なるものとして判定するため、データベースにアクセスして返却されるのは、意図しないEJB objectとなります。
例えば、以下のようにfindByPrimaryKeyメソッドを実行した場合、初回のfindByPrimaryKeyメソッドでDBアクセス(SELECT文発行)して、取得したデータをPrimary Keyの変数に格納します。
項目長分のデータが入っていない固定長文字列のDBカラムからデータを取り出した場合、Primary Keyの変数にはスペースを補完した値が設定されて、EJB objectがキャッシュされます。
2回目のfindByPrimaryKeyでは、findByPrimaryKeyの入力パラメタであるPrimary Keyをキーに、すでに検索されているEJB objectであるかを、コンテナ内のキャッシュから検索します。
UserTransaction.begin
SampleRemote EO1 = SampleHome.findByPrimaryKey(PK1) ※
更新処理
SampleRemote EO2 = SampleHome.findByPrimaryKey(PK1) ※
更新処理
UserTransaction.rollback
※PK1は同じPrimaryKey値
上記EO1とEO2では、異なるEJB objectが返却されるため、3.や5.の更新処理が反映されないといった問題が発生する可能性があります。
固定長文字列のDBカラムをプライマリキーとして使用する場合は、以下を考慮してください。
DBカラムを固定長項目から可変長項目に変更する。
PrimaryKeyクラスのhashcodeメソッド、および、equalsメソッド内でDBの固定長項目にマッピングしている変数を参照する場合、後方スペースを削除する。
CMPでプライマリキーのフィールドが1つの場合
CMPでプライマリキーのフィールドが1つの場合で、フィールドが以下の型の場合には、Primary Keyクラスを作成しないことも可能です。
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double
java.math.BigDecimal
java.sql.Date
java.sql.Time
java.sql.Timestamp
java.lang.String
この場合、通常はPrimary Keyクラスを指定するHomeインタフェースのcreateメソッドやfindByPrimaryKeyメソッドなどの引数には以下のように、プライマリキーのフィールドを指定します。
例
プライマリキーがString型の場合
public SampleRemote create(String pkField) throws javax.ejb.DuplicateKeyException, javax.ejb.CreateException, java.rmi.RemoteException; public SampleRemote findByPrimaryKey(String pkValue) throws javax.ejb.FinderException, javax.ejb.ObjectNotFoundException, java.rmi.RemoteException;
また、deployment descriptorの“Primary Keyクラス名”にはプライマリキーのフィールドの型(java.lang.Stringなど)を指定し、“Primary Keyフィールド名”にはフィールド名を指定してください。