CMP エンティティ bean (1.1 仕様)

EJB 2.0 では、アプリケーションサーバが EJB 2.0 スタイルの CMP だけではなく、EJB 1.1 スタイルの CMP もサポートする必要があります。JRun EJB 1.1 CMP を使用する場合は、jrun-ejb-jar.xml ファイルでパーシスタンスロジックを指定します。

ヒント:  エンタープライズデプロイウィザードを使用すると、パーシスタンスロジックを生成できます。詳細については、 「エンタープライズデプロイウィザード」 を参照してください。

ホームインターフェイス

エンティティ bean のホームインターフェイスには、任意の数の引数を持つ create メソッドが含まれている場合と含まれていない場合があります。各 create メソッドには、bean 実装の同じ引数に一致する ejbCreate メソッドが 1 つ必要です。エンティティ bean には、少なくとも findByPrimaryKey のfinder メソッドが含まれている必要があります。これは、bean 実装の ejbFindByPrimaryKey メソッドに対応しています。リモートホームインターフェイスメソッドは RemoteException を投げる必要があり、またすべての create メソッドは CreateException を投げる必要があります。

次のコードは、CMP 1.1 エンティティ bean のリモートホームインターフェイスを示しています。

package samples.cmp11;
import javax.ejb.FinderException;
import java.util.Collection;
import java.rmi.RemoteException;

public interface EmployeeHome extends javax.ejb.EJBHome {
  public Employee create(java.lang.String employeeId, 
java.lang.String firstName, 
 java.lang.String lastName, java.lang.String phone)
            throws java.rmi.RemoteException, 
javax.ejb.CreateException;
  public Employee findByPrimaryKey(java.lang.String pk)
            throws java.rmi.RemoteException, 
javax.ejb.FinderException;
  public Collection findAll()
            throws java.rmi.RemoteException, 
javax.ejb.FinderException;
  public Collection findByLastName(String lastName)
            throws java.rmi.RemoteException, 
javax.ejb.FinderException;
}

コンポーネントインターフェイス

次のコードは、CMP 1.1 エンティティ bean のリモートコンポーネントインターフェイスを示しています。

package samples.cmp11;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface Employee extends EJBObject {
  public String getEmployeeId() throws RemoteException;
  public void setEmployeeId(String employeeId) throws RemoteException;
  public String getFirstName() throws RemoteException;
  public void setFirstName(String firstName) throws RemoteException;
  public String getLastName() throws RemoteException;
  public void setLastName(String lastName) throws RemoteException;
  public String getPhone() throws RemoteException;
  public void setPhone(String phone) throws RemoteException;
}

bean 実装

CMP 1.1 エンティティ bean の一般的な必要条件は次のとおりです。

エンティティ bean の bean 実装には、setEntityContext、必要なコールバックメソッドおよびビジネスメソッドが含まれます。

次のコードは、CMP 1.1 エンティティ bean のリモートの bean 実装を示しています。

package samples.cmp11;
import javax.ejb.EntityContext;
import javax.ejb.RemoveException;
import javax.ejb.FinderException;
import java.util.Collection;
import java.rmi.RemoteException;

public class EmployeeBean implements javax.ejb.EntityBean {

    private EntityContext context;
    // フィールドは、データベースの列に対応しています。
    public String employeeId;
    public String firstName;
    public String lastName;
    public String phone;

    public String ejbCreate(String employeeId, String firstName, 
String lastName, String phone) {
        this.employeeId = employeeId;
        this.firstName = firstName;
        this.lastName = lastName;
        this.phone = phone;
        return null;
    }

    public void ejbPostCreate(String employeeId, String firstName, 
String lastName, String phone) {
    }

    public String getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public void setEntityContext(EntityContext context) {
        this.context = context;
    }
    public void unsetEntityContext() {
        this.context = null;
    }
    // CMP は、これらのコールバックメソッドを自動処理します。
    public void ejbActivate() {  }
    public void ejbPassivate() {  }
    public void ejbLoad() {  }
    public void ejbStore() {  }
    public void ejbRemove() throws RemoveException {  }
}

EJB デプロイメントディスクリプタ

CMP 1.1 エンティティ bean のデプロイメントディスクリプタには、entity 要素内に要素が含まれます。jrun-ejb-jar.xml ファイルのパーシスタンスアクションを指定する必要もあります。また、アプリケーションアセンブル担当者は、assembly-descriptor 要素内に追加仕様を作成できます。

次のサンプルは、CMP 1.1 エンティティ bean のデプロイメントディスクリプタ内の基本要素を示しています。

...
  <entity>
    <ejb-name>Employee</ejb-name>
    <ejb-class>samples.cmp11.EmployeeBean</ejb-class>
    <home>samples.cmp11.EmployeeHome</home>
    <remote>samples.cmp11.Employee</remote>
    <persistence-type>Container</persistence-type>
    <primkey-field>employeeId</primkey-field>
    <prim-key-class>java.lang.String</prim-key-class>
    <reentrant>True</reentrant>
    <cmp-version>1.x</cmp-version>
    <cmp-field>
        <field-name>employeeId</field-name>
    </cmp-field>
    <cmp-field>
        <field-name>firstName</field-name>
    </cmp-field>
    <cmp-field>
        <field-name>lastName</field-name>
    </cmp-field>
    <cmp-field>
        <field-name>phone</field-name>
    </cmp-field>
</entity>
...

JRun EJB デプロイメントディスクリプタ

jrun-ejb-jar.xml ファイルには、CMP パーシスタンスのアクションなど、JRun 特有のデプロイ設定が含まれます。各アクション (作成、ロード、保管など) は、必要に応じてデータベースにアクセスする SQL ステートメントに対応します。次のようにデータソースを指定します。

次のサンプルは、EJB 1.1 CMP エンティティ bean の JRun EJB デプロイメントディスクリプタを示しています。

...
<entity>
      <ejb-name>Employee</ejb-name>
      <jndi-name>Employee</jndi-name>
      <jdbc-mappings>
        <jdbc-mapping>
          <name>create</name>
          <statement>
           <action>INSERT INTO employees (employee_id , first_name , 
      last_name, phone) VALUES ( ?, ? , ? , ?)</action>
            <source>samples</source>
            <params>
              <param>
                 <name>employeeId</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>firstName</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>lastName</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>phone</name>
                 <type>VARCHAR</type>
              </param>
            </params>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>load</name>
          <statement>
            <action>SELECT employee_id, first_name, last_name, phone 
      FROM employees WHERE employee_id=?</action>
            <source>samples</source>
            <params>
              <param>
                 <name>employeeId</name>
                 <type>VARCHAR</type>
              </param>
            </params>
            <fields>
              <field>employeeId</field>
              <field>firstName</field>
              <field>lastName</field>
              <field>phone</field>
            </fields>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>remove</name>
          <statement>
            <action>DELETE FROM employees WHERE employee_id=?</action>
            <source>samples</source>
            <params>
              <param>
                 <name>employeeId</name>
                 <type>VARCHAR</type>
              </param>
            </params>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>store</name>
          <statement>
            <action>UPDATE employees SET first_name=?, last_name=?, 
      phone=?WHERE employee_id=?</action>
            <source>samples</source>
            <params>
              <param>
                 <name>firstName</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>lastName</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>phone</name>
                 <type>VARCHAR</type>
              </param>
              <param>
                 <name>employeeId</name>
                 <type>VARCHAR</type>
              </param>
            </params>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>findAll</name>
          <statement>
            <action>SELECT employee_id FROM employees</action>
            <source>samples</source>
            <fields>
              <field>employeeId</field>
            </fields>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>findByLastName</name>
          <statement>
            <action>SELECT employee_id FROM employees WHERE 
      last_name=?1</action>
            <source>samples</source>
            <params>
              <param>
                 <name>lastName</name>
                 <type>VARCHAR</type>
              </param>
            </params>
            <fields>
              <field>employeeId</field>
            </fields>
          </statement>
        </jdbc-mapping>
        <jdbc-mapping>
          <name>findByPrimaryKey</name>
          <statement>
            <action>SELECT employee_id FROM employees WHERE 
      employee_id=?</action>
            <source>samples</source>
            <params>
              <param>
                 <name>employeeId</name>
                 <type>VARCHAR</type>
              </param>
            </params>
            <fields>
              <field>employeeId</field>
            </fields>
          </statement>
        </jdbc-mapping>
      </jdbc-mappings>
    </entity>
...

サンプルクライアント

サンプルクライアントを表示するには、samples JRun サーバを起動し、ブラウザで http://localhost:8200/techniques を開きます。

JRun CMP 1.1 の追加検討事項

JRun EJB コンテナは、次の機能によって CMP 1.1 開発の負担を軽減します。

テーブルの自動作成と自動削除

jrun-ejb-jar.xml ファイルで create-table 要素が true に設定されている場合、JRun は、createTable jdbc-mapping 要素で指定されたとおりにテーブル作成 DDL (Data Definition Language:データ定義言語) を実行します。また、JRun は delete-table 要素と deleteTable jdbc-mapping 要素を使用して、テーブル削除ロジックを実行します。この機能は、常に正式なデータベーステーブルのコピーを使用してテストを開始できるので、開発サイクルの段階で役立ちます。次の jrun-ejb-jar.xml の抜粋は、テーブルの自動作成と自動削除のステートメントを示しています。

...
<create-table>true</create-table>
<delete-table>true</delete-table>
...
<jdbc-mapping>
  <name>createTable</name>
  <statement>
    <action>CREATE TABLE public.EntityTestBeanTable (id INTEGER, value 
VARCHAR(32))</action>
    <source>samples</source>
    <params />
    <fields />
  </statement>
</jdbc-mapping>
<jdbc-mapping>
  <name>deleteTable</name>
  <statement>
    <action>DROP TABLE public.EntityTestBeanTable</action>
    <source>samples</source>
    <params />
    <fields />
</statement>
</jdbc-mapping>
...

create-table 要素が true に設定されていて、createTable jdbc-mapping 要素がファイルにない場合、JRun は「"SQL の自動生成" 」で説明するようにデフォルトの DDL を生成します。

SQL の自動生成

基本的なメソッドステートメント (createloadstoreremovefindByPrimaryKeycreateTable、および deleteTable) のいずれかに jrun-ejb-jar.xml ファイルの
jdbc-mapping が含まれていない場合、JRun は、ejb-jar.xml ファイルで指定されている EJB 名と CMP フィールドに基づいて、デフォルトの SQL 実装を作成します。この機能を使用するには、EJB 名がデータベースのテーブル名に一致し、cmp-field 要素がそのデータベーステーブルの列名に一致している必要があります。

メモ:  テーブルを作成および削除する場合、EJB コンテナは、create-table および
delete-table 要素が true に設定されている場合にのみ SQL を生成します。

1 つのパーシスタンスアクションで複数の SQL ステートメントを実行

JRun では、各 jdbc-mapping 要素に対して複数の statement 要素を指定できます。この機能を使用して、各パーシスタンスアクションによる複数のデータベースへのアクセスなど、カスタマイズしたパーシスタンス処理を実行できます。EJB コンテナは、jdbc-mapping 要素に定義された順序でステートメントを実行します。

次の例は、jdbc-mapping 要素に関連付けられた statement 要素のコーディング方法を示しています。

...
<jdbc-mapping>
  <name>create</name>
  <statement>
    <action>INSERT INTO employee( empid , lastname, firstname) 
      VALUES( ?, ? , ? , ? , ?)</action>
    <source>samples</source>
    <params>
      <param>
        <name>empid</name>>
        <type>VARCHAR</type>
      </param>
      <param>
        <name>lastname</name>
        <type>VARCHAR</type>
      </param>
      <param>
        <name>firstname</name>
        <type>VARCHAR</type>
      </param>
    </params>
    <fields />
  </statement>
  <statement>
...
  </statement>  
</jdbc-mapping>
...