ヘッダーをスキップ
Oracle Containers for J2EE Orion CMP開発者ガイド
10g(10.1.3.1.0)
B31855-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

5 コンテナ管理の永続性を持つEJB 2.0エンティティBeanの構成

この章では、コンテナ管理の永続性を持つEJB 2.0エンティティBeanを使用するために構成が必要な各種のオプションについて説明します。

表5-1にこれらのオプションを一覧表示し、基本オプション(ほとんどのアプリケーションに適用可能)であるか、拡張オプション(より専門的なアプリケーションに適用可能)であるかを示します。

表5-1 コンテナ管理の永続性を持つEJB 2.0エンティティBeanに対する構成可能オプション

オプション タイプ

主キーの構成


基本

コンテナ管理の永続フィールドの構成


基本

コンテナ管理の関連フィールドの構成


基本

データベース分離レベルの構成


拡張

並行性モードの構成


拡張

データベースへの排他的書込みアクセスの構成


拡張

コンテナ管理の永続性を持つEJB 2.0エンティティBeanに対するコールバック・メソッドの構成


拡張



注意:

コンテナ管理の永続性を持つエンティティBeanの構成では、JDeveloper IDEを使用することをお薦めします。JDeveloperにエンティティBeanとデータベース表の間の複雑なマッピングを管理する機能があることがその理由です。詳細は、「コンテナ管理の関連フィールドの構成」「JDeveloperの使用」を参照してください。

詳細は次のトピックを参照してください。

主キーの構成

各エンティティBeanインスタンスには、他のインスタンスとは一意に区別される主キーがあります。主キー(または複合主キー内に含まれるフィールド)は、デプロイメント・ディスクリプタ内のコンテナ管理の永続フィールドとして宣言する必要があります。

この項では主キー構成の次の内容について説明します。

主キー・フィールドの構成

主キー内のすべてのフィールドはプリミティブ、シリアライズ可能、またはSQL型にマップ可能な型のいずれかに制限されます。主キーは次のどちらかの方法で定義できます。

  • 主キーの型を既知の型に定義します。この型はデプロイメント・ディスクリプタの<prim-key-class>要素で定義されます。永続主キーとして識別されるデータ・フィールドは、デプロイメント・ディスクリプタの<primkey-field>要素で識別されます。Beanクラス内で宣言される主キー変数はpublicとして宣言する必要があります。

    主キー定義の拡張オプションとは、その型を、シリアライズ可能な<NAME>PKクラス内のシリアライズ可能オブジェクトとして定義することです。このクラスはデプロイメント・ディスクリプタの<prim-key-class>で宣言されます。詳細は「主キー・クラスの構成」を参照してください。

  • 自動的に生成される主キーを指定します。<prim-key-class>java.lang.Objectを主キー・クラス型として指定する場合に、主キー名を<primkey-field>で指定しないと、主キーは自動的にコンテナで生成されます。詳細は「主キーの自動生成の構成」を参照してください。

例5-1 デプロイメント・ディスクリプタ内における既知の型の主キーの定義

単純なCMPについて、デプロイメント・ディスクリプタ内で主キーのデータ型を定義することで主キーを既知の型として定義できます。例5-1は主キー(従業員番号)をjava.lang.Integerとして定義する例を示しています。

<enterprise-beans>
    <entity>
        <display-name>Employee</display-name>
        <ejb-name>EmployeeBean</ejb-name>
        <local-home>employee.EmployeeLocalHome</local-home>
        <local>employee.EmployeeLocal</local>
        <ejb-class>employee.EmployeeBean</ejb-class>
        <persistence-type>Container</persistence-type>
        <prim-key-class>java.lang.Integer</prim-key-class>
        <reentrant>False</reentrant>
        <cmp-version>2.x</cmp-version>
        <abstract-schema-name>Employee</abstract-schema-name>
        <cmp-field><field-name>empNumber</field-name></cmp-field>
        <cmp-field><field-name>empName</field-name></cmp-field>
        <cmp-field><field-name>salary</field-name></cmp-field>
        <primkey-field>empNumber</primkey-field>
    </entity>
...
</enterprise-beans>

一度主キーを定義すると、コンテナが主キーに対するエンティティBean表の列を作成し、デプロイメント・ディスクリプタで定義された主キーをこの列にマップします。

orion-ejb-jar.xmlファイル内で、ejb-jar.xmlファイルで定義されたコンテナ管理の永続フィールドまたは主キー・フィールドをデータベース列名にマップすることで、主キーが基底となるデータベース永続記憶域にマップされます。次のorion-ejb-jar.xmlフラグメントでは、jdbc/OracleDSデータ・ソースで定義されるデータベースでEmpBean永続記憶域がEMP表として定義されます。<entity-deployment>要素の定義(表A-1「<entity-deployment>要素の属性」を参照)に従って、主キーのempNumberEMP表のEMPNUMBER列にマップされ、empNameおよびsalary永続フィールドがEMP表でそれぞれEMPNAMEおよびSALARY列にマップされます。

<entity-deployment name="EmpBean" ...table="EMP" data-source="jdbc/OracleDS"...>
    <primkey-mapping>
        <cmp-field-mapping name="empNumber" persistence-name="EMPNUMBER" />
    </primkey-mapping>
    <cmp-field-mapping name="empName" persistence-name="EMPNAME" />
    <cmp-field-mapping name="salary" persistence-name="SALARY" />
...

主キー・クラスの構成

主キーが単純なデータ型よりも複雑な場合、主キーは<NAME>PKというシリアライズ可能なクラスである必要があります。主キー・クラスはデプロイメント・ディスクリプタの<prim-key-class>要素で定義します。

主キー変数は次の条件に従う必要があります。

  • デプロイメント・ディスクリプタの<cmp-field><field-name>要素で定義されること。これによってコンテナが主キー・フィールドを管理できます。

  • Beanクラス内でpublicとして宣言され、プリミティブ、シリアライズ可能、またはSQL型にマップ可能な型のいずれかに制限されること。

  • 主キーを構成する変数の名前が、<cmp-field><field-name>要素と主キー・クラスの両方で同じであること。

主キー・クラス内で、ユーザーは主キー・インスタンスを作成するためのコンストラクタを実装します。主キー・クラスをこの方法で一度定義すると、コンテナがクラスを管理します。

例5-2 主キー・クラスの定義

例5-2では主キー・クラス内に従業員番号が置かれています。

package employee;

public class EmployeePK implements java.io.Serializable {

    public Integer empNumber;

    public EmployeePK() {
        this.empNumber = null;
    }

    public EmployeePK(Integer newEmpNumber) {
        this.empNumber = newEmpNumber;
    }

}

例5-3 デプロイメント・ディスクリプタの主キー・クラスの宣言

例5-3のように、主キー・クラスはデプロイメント・ディスクリプタの<prim-key-class>要素内で宣言され、その各変数は<cmp-field><field-name>要素内で宣言されます。

<enterprise-beans>
    <entity>
        <description>no description</description>
        <display-name>EmployeeBean</display-name>
        <ejb-name>EmployeeBean</ejb-name>
        <local-home>employee.EmployeeLocalHome</local-home>
        <local>employee.EmployeeLocal</local>
        <ejb-class>employee.EmployeeBean</ejb-class>
        <persistence-type>Container</persistence-type>
        <prim-key-class>employee.EmployeePK</prim-key-class>
        <reentrant>False</reentrant>
        <cmp-version>2.x</cmp-version>
        <abstract-schema-name>Employee</abstract-schema-name>
        <cmp-field><field-name>empNumber</field-name></cmp-field>
        <cmp-field><field-name>empName</field-name></cmp-field>
        <cmp-field><field-name>salary</field-name></cmp-field>
    </entity>
...
</enterprise-beans>

ユーザーが一度主キーを定義すると、コンテナが主キーに対するエンティティBean表の列を作成し、デプロイメント・ディスクリプタで宣言された主キー・クラスをこの列にマップします。

永続フィールドは、「主キーの構成」で説明されているのと同じ方法でorion-ejb-jar.xmlにマップされます。複合主キーでは、マッピングに複数のフィールドが含まれるため、<primkey-mapping>要素の<cmp-field-mapping>要素には別の<fields>下位要素が含まれます。主キーのあらゆるフィールドは、<fields>要素の別々の<cmp-field-mapping>要素で次のように定義されます。

<primkey-mapping>
    <cmp-field-mapping>
        <fields>
            <cmp-field-mapping name="empNumber" persistence-name="EMPNUMBER" />
        </fields>
    </cmp-field-mapping>
</primkey-mapping>


注意:

外部キーを含む複合主キーがある場合は、特別なマッピングが必要です。詳細は「複合主キー内の外部キーの構成」を参照してください。

複合主キー内の外部キーの構成

EJB 2.0仕様では、エンティティBeanに対する主キーはejbCreateメソッド内で初期化する必要があります。ただし、このメソッドではこのBeanの別のBeanとの関連を設定できません。外部キーでこの関連を最も早く設定できるのは、ejbPostCreateメソッドです。

つまり、複合主キー内に外部キーがある場合、ユーザーは、ejbCreateメソッドで複合主キー内のすべてのフィールドを設定する必要があるにもかかわらず、このメソッドでは外部キーを設定できないという問題に直面します。

次の仮説シナリオではこの問題の回避策をモデル化します。このシナリオでは、ある注文に1つ以上の商品が含まれる可能性があり、注文Beanの中には多数の商品があり、各商品は各注文に属します。商品に対する主キーは、商品識別子と注文識別子で構成される複合主キーです。注文識別子は注文を示す外部キーです。

ユーザーは実際の外部キー・フィールドを模倣するプレースホルダ永続フィールドを追加するため、デプロイメント・ディスクリプタとBean実装を変更する必要があります。このフィールドはejbCreateメソッドの際に設定されます。ただし、プレースホルダ永続フィールドと外部キーは同じデータベース列を示します。実際の外部キーはejbPostCreateメソッドの際に更新されます。


注意:

ejb-jar.xmlファイルをプレースホルダ永続フィールドと外部キーで変更します。表を作成せずにorion-ejb-jar.xmlファイルを自動的に生成するため、orion-application.xmlファイルの<autocreate-tables>要素をfalseに設定してアプリケーションをデプロイします。次に、正しいデータベース列を示すようにorion-ejb-jar.xmlファイルを変更し、<autocreate-tables>要素をtrueに設定してから再デプロイします。

例5-4 主キー内に外部キーを内包するためのデプロイメント・ディスクリプタとBeanコードの変更

例5-4はデプロイメント・ディスクリプタとBean実装の両方の変更例を示しています。

注文シナリオでは、各注文に1つ以上の商品が含まれます。OrderBeanは注文を表し、OrderItemBeanは注文の商品を表します。各商品には、商品番号と、その商品が属する注文番号で構成される主キーがあります。つまり、商品に対する主キーには注文Beanを示す外部キーが含まれます。

複合主キーに対する調整を行うには、ejb-jar.xmlファイルを次のように変更します。

  1. 主キーの永続フィールドを外部キーに対するプレースホルダとして定義します。このプレースホルダは複合主キー・クラス定義で使用されます。

    例5-4で、orderId永続フィールドは<cmp-field>要素で定義されます。orderIdおよびitemId永続フィールドは、OrderItemPK.javaにおける複合主キーの識別に使用されます。

  2. 主キー定義外の外部キーを、<relationships>セクションの<cmr-field>要素で定義します。

    例5-4で、belongToOrder外部キーはOrderItemBeanに対する<cmr-field>要素で定義され、商品から注文への関係を定義します。

<entity>
    <ejb-name>OrderItemBean</ejb-name>
    <local-home>OrderItemLocalHome</local-home>
    <local>OrderItemLocal</local>
    <ejb-class>OrderItemBean</ejb-class>
    ...
    <cmp-field><field-name>itemId</field-name></cmp-field>
    <cmp-field><field-name>orderId</field-name></cmp-field>
    <cmp-field><field-name>price</field-name></cmp-field>
    <prim-key-class>OrderItemPK</prim-key-class>
    ...
</entity>
<relationships>
    <ejb-relation>
        <ejb-relation-name>Order-OrderItem</ejb-relation-name>
        <ejb-relationship-role>
            <ejb-relationship-role-name>
                Order-Has-OrderItems
            </ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source>
                <ejb-name>OrderBean</ejb-name>
            </relationship-role-source>
            <cmr-field>
                <cmr-field-name>items</cmr-field-name>
                <cmr-field-type>java.util.Collection</cmr-field-type>
            </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
            <ejb-relationship-role-name>
                OrderItems-from-Order
            </ejb-relationship-role-name>
            <multiplicity>Many</multiplicity>
            <cascade-delete/>
            <relationship-role-source>
                <ejb-name>OrderItemBean</ejb-name>
            </relationship-role-source>
            <cmr-field>
                <cmr-field-name>belongToOrder</cmr-field-name>
            </cmr-field>
        </ejb-relationship-role>
...

OrderItemPK.javaクラスは複合主キーの内容を次のように定義します。

public class OrderItemPK implements java.io.Serializable {

    public Integer itemID;
    public Integer orderID;

    public OrderItemPK() {
        this.itemId = null;
        this.orderId = null;
    }

    public OrderItemPK(Integer newItemId, Integer newOrderId) {
        this.itemId = newItemId;
        this.orderId = newOrderId;
    }

    public boolean equals(Object o) {
        if (o instanceof OrderItemPK) {
            OrderItemPK pk = (OrderItemPK) o;
            if (pk.itemId.intValue() == itemId.intValue() &&
                pk.orderId.intValue() == orderId.intValue()) {
                return true;
            }
        }
        return false;
    }

    public int hashCode() {
        return itemId.hashCode() * orderId.hashCode();
    }
}

自動作成されるデータベース表で十分な場合は、orion-ejb-jar.xmlファイルを変更する必要はありません。ただし、既存のデータベース表にマップする必要がある場合は、その表を指すようにorion-ejb-jar.xmlファイルを変更する必要があります(詳細は「関連フィールドのデータベースに対する明示的マッピングの構成」を参照)。

orion-ejb-jar.xmlファイルの自動生成後、これをユーザーの開発ディレクトリにコピーします。データベース列名は、それぞれの永続フィールド名および関連フィールド名マッピングのpersistence-name属性で定義されます。プレースホルダ永続フィールドと外部キーの両方に対するpersistence-name属性は、必ず同じものにします。

Order/OrderItem例に対するorion-ejb-jar.xmlファイルを次に示します。

<entity-deployment name="OrderItemBean"  table="ORDER_ITEM">
    <primkey-mapping>
        <cmp-field-mapping name="itemId" persistence-name="Item_ID" />
        <cmp-field-mapping name="orderId" persistence-name="Order_ID" />
    </primkey-mapping>
    <cmp-field-mapping name="price" persistence-name="Price" />
    <cmp-field-mapping name="belongToOrder">
        <entity-ref home="OrderBean">
            <cmp-field-mapping name="belongToOrder" persistence-name="Order_ID" />
        </entity-ref>
    </cmp-field-mapping>
</entity-deployment>

<entity-deployment name="OrderBean"  table="ORDER">
    <primkey-mapping>
        <cmp-field-mapping name="orderId" persistence-name="Order_ID" />
    </primkey-mapping>
    <cmp-field-mapping name="orderDesc" persistence-name="Order_Description" />
    <cmp-field-mapping name="items">
        <collection-mapping table="ORDER_ITEM">
            <primkey-mapping>
                <cmp-field-mapping name="OrderBean_orderId">
                    <entity-ref home="OrderBean">
                        <cmp-field-mapping name="OrderBean_orderId">
                    </entity-ref>
                </cmp-field-mapping>
            </primkey-mapping>
            <value-mapping type="OrderItemLocal">
                <cmp-field-mapping name="OrderItemBean_itemId">
                    <entity-ref home="OrderItemBean">
                        <cmp-field-mapping name="OrderItemBean_itemId">
                                <cmp-field-mapping name="OrderItemBean_itemId">
                            </fields>
                        </cmp-field-mapping>
                    </entity-ref>
                </cmp-field-mapping>
            </value-mapping>
            </collection-mapping>
        </cmp-field-mapping>
</entity-deployment>

Order/OrderItemの例において、orion-ejb-jar.xmlファイルのOrderItemBeanに対する<entity-deployment>表A-1「<entity-deployment>要素の属性」を参照)セクションでは、次のことが行われます。

  • 表がtable属性で定義されます。この例ではORDER_ITEMです。

  • itemIdの列名はpersistence-name属性でItem_IDとして定義されます。

  • プレースホルダ永続フィールドのorderIdの列名は、persistence-name属性でOrder_IDとして定義されます。

  • 外部キーのbelongToOrderは、プレースホルダ永続フィールドのorderIdと同じ列の、Order_IDデータベース列にマップされます。

外部キー(belongToOrder)とプレースホルダ永続フィールド(orderId)は両方とも同じデータベース列を示します。

最後に、プレースホルダ永続フィールドおよび外部キーの双方と連携するように、Bean実装を次のように更新します。

  1. ejbCreateメソッドで、次の作業を実行します。

    • 外部キー・フィールドのかわりとなるプレースホルダ永続フィールドを作成します。

    • ejbCreateメソッドでプレースホルダ永続フィールドに値を設定します。この値はデータベース表の外部キー・フィールドに書き込まれます。

  2. ejbPostCreateメソッドで、外部キーを重複した永続フィールドの値に設定します。


    注意:

    外部キーは主キーの一部であるため、設定できるのは1回のみです。

Order/OrderItemの例で、orderId永続フィールドはejbCreateメソッドで設定され、belongToOrder関連フィールドはejbPostCreateメソッドで設定されます。

public OrderItemPK ejbCreate(OrderItem orderItem) throws CreateException {
    setItemId(orderItem.getItemId());
    setOrderId(orderItem.getOrderId());
    setPrice(orderItem.getPrice());
    return new OrderItemPK(orderItem.getItemId(),orderItem.getOrderId());
}

public void ejbPostCreate(OrderItem orderItem) throws CreateException {
    // right after the bean has been created
    try {
        Context ctx = new InitialContext();
        OrderLocalHome orderHome =
                      (OrderLocalHome)ctx.lookup("java:comp/env/OrderBean");
        OrderLocal order = orderHome.findByPrimaryKey(orderItem.getOrderId());
        setBelongToOrder(order);
    }
    catch(Exception e) {
        e.printStackTrace();
        throw new EJBException(e);
    }
}

ejbCreateおよびejbPostCreateメソッドに渡されるOrderItemオブジェクトに対するコードを次に示します。

public class OrderItem implements java.io.Serializable {

    private Integer itemId;
    private Integer orderId;
    private Double price;

    public OrderItem(Integer itemId, Integer orderId, Double price) {
        this.itemId = itemId;
        this.orderId = orderId;
        this.price = price;
    }

    public Integer getItemId() {
        return itemId;
    }

    public void setItemId(Integer itemId) {
        this.itemId = itemId;
    }

    public Integer getOrderId() {
        return orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public boolean equals(Object other) {
        if (other instanceof OrderItem) {
            OrderItem orderItem = (OrderItem)other;
            if (itemId.equals(orderItem.getItemId()) &&
                orderId.equals(orderItem.getOrderId()) &&
                price.equals(orderItem.getPrice()) ) {
                return true;
            }
        }
        return false;
    }
}

主キーの自動生成の構成

デプロイメント・ディスクリプタの<prim-key-class>要素でjava.lang.Objectを主キー・クラス型として指定する場合に、主キー名を<primkey-field>要素で指定しないと、主キーは自動的にコンテナで生成されます。

<enterprise-beans>
    <entity>
        <display-name>Employee</display-name>
        <ejb-name>EmployeeBean</ejb-name>
        <local-home>employee.EmployeeLocalHome</local-home>
        <local>employee.EmployeeLocal</local>
        <ejb-class>employee.EmployeeBean</ejb-class>
        <persistence-type>Container</persistence-type>
        <prim-key-class>java.lang.Object</prim-key-class>
        <reentrant>False</reentrant>
        <cmp-version>2.x</cmp-version>
        <abstract-schema-name>Employee</abstract-schema-name>
        <cmp-field><field-name>empNumber</field-name></cmp-field>
        <cmp-field><field-name>empName</field-name></cmp-field>
        <cmp-field><field-name>salary</field-name></cmp-field>
    </entity>
...
</enterprise-beans>

一度主キーを定義すると、コンテナがLONG型の主キーに対するエンティティBean表のautoidという列を作成します。コンテナは主キー値に乱数を使用します。これはBeanのorion-ejb-jar.xmlで次のように生成されます。

<primkey-mapping>
    <cmp-field-mapping name="auto_id" persistence-name="autoid"/>
</primkey-mapping>

コンテナ管理の永続フィールドの構成

コンテナ管理の永続フィールドは、データベース表に永続する単純なデータ型を表します。これらのフィールドはエンティティBeanの状態を定義します。これらのフィールドはBeanの直接属性です。永続フィールドの詳細は、「コンテナ管理の永続フィールド」を参照してください。

コンテナ管理の永続性を持つエンティティBeanで、次の方法でBeanインスタンスとデプロイメント・ディスクリプタの両方に永続データを定義します。

これらのフィールドを、データベースに次のようにマップします。

永続フィールドのデータベースに対するデフォルト・マッピングの構成

ejb-jar.xmlファイルで永続フィールドを単純に定義する場合、OC4Jではこれらのフィールドのデータベースに対する次のようなマッピングが提供されます。

  • データベース: 使用中のOC4Jインスタンス構成に設定されているデフォルトのデータベース。JNDI名については、エミュレートされたデータ・ソースには<location>要素を、エミュレートされていないデータ・ソースには<ejb-location>要素を使用します。

    インストール後の状態では、デフォルト・データベースはローカルにインストールされたOracleデータベースで、ORCLというSIDでポート1521でリスニングするデータベースです。デフォルト・データベースをカスタマイズするには、最初に構成されたデータベースを、ユーザーのデータベースを指すように変更します。

  • 表: コンテナは、表名の一意性が保証されたデフォルト表を自動的に作成します。今後の再デプロイの場合に備えて、この表名で生成されたorion-ejb-jar.xmlファイルを、ejb-jar.xmlファイルと同じディレクトリにコピーします。これによって、今後の再デプロイの際に最初に生成された表名と同じ名前を使用できます。このファイルをコピーしないと、異なる表名が生成される可能性があります。

    表名は次の名前で構成され、それぞれの名前はアンダースコア文字( _ )で区切られます。

    • デプロイメント・ディスクリプタの<ejb-name>で定義されるEJB名。

    • .jar拡張子を含むJARファイル名。ただし、SQL表記規則に従ってダッシュ文字( - )およびピリオド( . )はすべてアンダースコア文字( _ )に変換されます。たとえば、JARファイルの名前がemployee.jarの場合は、employee_jarが名前に付加されます。

    • デプロイ時にユーザーが定義したアプリケーション名。

    構成された名前が30文字を超えている場合、この名前は24文字で切り捨てられます。その後に、英数字ハッシュ・コードで構成される6文字が名前に付加されます。

    たとえば、EJB名がEmpBeanで、JARファイルがempl.jarで、アプリケーション名がemployeeの場合、デフォルトの表名はEmpBean_empl_jar_employeeになります。

  • 列名: エンティティBean表の各列は指定されたデータベースの<cmp-field>要素と同じ名前を持ちます。Javaデータ型をデータベース・データ型に変換した、データベースに対するデータ型は、oracle.xmlなどの特定のデータベースXMLファイルで定義されます。

永続フィールドのデータベースに対する明示的マッピングの構成

「永続フィールドのデータベースに対するデフォルト・マッピングの構成」で説明したように、ユーザーの永続データはコンテナを使用してデータベース表に自動的にマップできます。ただし、Beanで表されているデータがより複雑な場合、またはOC4Jで提供されるデフォルトを使用しない場合は、永続データをorion-ejb-jar.xmlファイル内の既存のデータベース表およびその列にマップすることができます。フィールドが一度マップされると、コンテナは永続データの永続記憶域を指定された表および行に提供します。

永続フィールドをデータベースに明示的にマップするには、次の手順を実行します。

  1. ejb-jar.xml要素のみが構成されたアプリケーションをデプロイします。

    OC4Jはデフォルト・マッピングが含まれるユーザー用のorion-ejb-jar.xmlファイルを作成します。これらのフィールドは作成するよりも変更する方が簡単です。

  2. ユーザーが指定したデータベース表および列を使用するように、orion-ejb-jar.xmlファイルの<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)を変更します。

<cmp-field>要素内でそれぞれにコンテナ管理の永続フィールドを一度定義すると、各フィールドを特定のデータベース表および列にマップできます。このように、これらの永続フィールドを既存のデータベース表にマップできます。マッピングはorion-ejb-jar.xmlファイル(OC4J固有デプロイメント・ディスクリプタ)で発生します。

永続フィールドの明示的マッピングは<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)内で完結します。この要素にはエンティティBeanに対するすべてのマッピングが含まれます。永続フィールド・マッピングに固有の属性および要素を次に示します。

<entity-deployment name="..." location="..." table="..." data-source="...">
    <primkey-mapping>
        <cmp-field-mapping name="..." persistence-name="..." />
    </primkey-mapping>
    <cmp-field-mapping name="..." persistence-name="..." />
...
</entity-deployment>

表5-2 特定のデータベース表へ永続フィールドをマッピングするためのデプロイメント・ディスクリプタの要素

要素または属性の名前 説明

name

ejb-jar.xmlファイルの<ejb-name>要素で定義されるBean名。

location

JNDIロケーション。

table

データベース表名。

data-source

表が存在するデータベースに対するデータ・ソース。

primkey-mapping

主キーを表にマップする方法の定義。

cmp-field-mapping

<cmp-field>はname属性によってデプロイメント・ディスクリプタに指定され、persistence-name属性で表の列にマップされます。


orion-ejb-jar.xmlファイル内で次のように構成を行います。

  1. マップ対象のコンテナ管理の永続フィールドを含むすべてのエンティティBeanに対して<entity-deployment>要素を構成します。

  2. マップするBean内のすべてのフィールドに対して<cmp-field-mapping>要素を構成します。各<cmp-field-mapping>要素には永続対象のフィールドの名前を次のように含む必要があります。

    1. <primkey-mapping>要素の<cmp-field-mapping>要素で主キーを構成します。

    2. 単一の<cmp-field-mapping>要素内で単一フィールドにマップされる単純なデータ型(プリミティブ、単純なオブジェクト、またはシリアライズ可能オブジェクトなど)を構成します。名前およびデータベース・フィールドはすべて要素の属性内で定義されます。

例5-5 永続フィールドの特定データベース表へのマッピング

例5-5は、従業員永続フィールドをOracleデータベース表のEMPにマップして、Beanインスタンスの永続フィールドをデータベース表および列にマップする例を示しています。

<entity-deployment name="EmpBean"
                   location="emp/EmpBean" wrapper="EmpHome_EntityHomeWrapper2"
                   max-tx-retries="3" table="emp" data-source="jdbc/OracleDS">
    <primkey-mapping>
        <cmp-field-mapping name="empNumber" persistence-name="empnumber" />
    </primkey-mapping>
    <cmp-field-mapping name="empName" persistence-name="ename" />
    <cmp-field-mapping name="salary" persistence-name="sal" />
...
</entity-deployment>

デプロイ後、OC4Jは表5-3のように要素値をマップします。

表5-3 コンテナによるデプロイメント・ディスクリプタの要素値のマッピング

Bean データベース

emp/EmpBean

data-sources.xmlファイルのjdbc/OracleDSに置かれているEMP

empNumber

主キーとしてのEMPNUMBER

empName

EMPNAME

salary

SALARY


コンテナ管理の関連フィールドの構成

関連フィールドは関連するBeanを特定します。関連フィールドはデータベース表における外部キーと同様に機能します。詳細は「関連フィールド」を参照してください。

関連フィールドは仮想的です。ユーザーはBeanクラスのコードでこれらのフィールドに対するgetterおよびsetterを次のように指定します。

public abstract void setContractInfo(ContractInfo contractInfo) throws RemoteException

public abstract ContractInfo getContractInfo() throws RemoteException

コンテナはこれらのメソッドの実装を提供します。

前述した例では、対応する関連フィールドはcontractInfoです。

デプロイメント・ディスクリプタで、このフィールドは<cmr-field><cmr-field-name>要素で次のように定義されます。

<ejb-ralation>
    ...
    <cmr-field>
        <cmr-field-name>contractInfo</cmr-field-name>
        <cmr-field-type>contractInfo</cmr-field-type>
    </cmr-field>
    ...
</ejb-ralation>

コンテナ管理の関連の詳細は、「コンテナ管理の関連」を参照してください。

各エンティティBeanがデータベースの表にマップされるに従って、その永続および関連フィールドがそれぞれデータベース表内の列に保存されます。これらのフィールドをデータベースにマップするには、次のどちらかを実行します。

関連フィールドのデータベースに対するデフォルト・マッピングの構成

ejb-jar.xmlファイルで関連フィールドを宣言する場合、OC4Jでは、orion-ejb-jar.xmlファイルの自動生成時に、これらのフィールドのデータベースに対するデフォルト・マッピングが提供されます。関連フィールドに対するデフォルト・マッピングは、永続フィールドに対するマッピングと同じです(「永続フィールドのデータベースに対するデフォルト・マッピングの構成」を参照)。


注意:

今後の再デプロイの場合に備えて、指示した表名で自動的に生成されたorion-ejb-jar.xmlファイルを、J2EE_Home/application-deploymentsディレクトリからejb-jar.xmlファイルと同じディレクトリにコピーします。これを実行しないと、それぞれの再デプロイの際に異なる表名が生成される可能性があります。

簡単にまとめると、デフォルト・マッピングには次のようなものが含まれます。

  • データベース: 使用中のOC4Jインスタンス構成に設定されているデフォルトのデータベース。

  • デフォルト表: 関連における各エンティティBeanは、基底となるデータベース表のデータを表します。エンティティBeanの基底表の名前は一意である必要があるため、名前は次の名前から構成されます。それぞれの名前はアンダースコア文字( _ )で区切られます。

    • デプロイメント・ディスクリプタの<ejb-name>要素で定義されるEJB名。

    • .jar拡張子を含むJARファイル名。ただし、SQL表記規則に従ってダッシュ文字( - )およびピリオド( . )はすべてアンダースコア文字( _ )に変換されます。たとえば、JARファイルの名前がaddress.jarの場合は、address_jarが名前に付加されます。

    • デプロイ時にユーザーが定義したアプリケーション名。

    構成された名前が30文字を超えている場合、この名前は24文字で切り捨てられます。アンダースコア文字( _ )、続いて英数字ハッシュ・コードで構成される5文字が名前に付加されて、一意性を確保します。

    たとえば、EJB名がAddressEntryで、JARファイル名がaddr.jarで、アプリケーション名がaddressの場合、デフォルトの表名はAddressEntry_addr_jar_addressになります。

  • 各表の列名: コンテナはデプロイメント・ディスクリプタで定義された<cmp-field>および<cmr-field>要素に基づいて、各表の列を生成します。列は、エンティティBeanデータに関連する各<cmp-field>要素に対して作成されます。また、関連を表す各<cmr-field>要素に対しても列が作成されます。単方向の関連(「CMRの方向」を参照)では、関連における一方のエンティティのみがデプロイメント・ディスクリプタで<cmr-field>を定義します。双方向の関連(「CMRの方向」を参照)では、関連における両方のエンティティが<cmr-field>を定義します。

    <cmr-field>要素について、コンテナは関連オブジェクトの主キーを示す外部キーを次のように作成します。

    • デフォルトの1対1関連では、外部キーはソース・エンティティBeanに対するデータベース表に作成され、ターゲット・データベース表の主キーに方向付けられます。たとえば1人の従業員に1つのアドレスがある場合、アドレス表の主キーを指す外部キーが従業員表の中に作成されます。

    • 1対多関連のデフォルトでは外部キーを使用します。

    • 多対多関連のデフォルトではアソシエーション表(第3表)を作成します。アソシエーション表には2つの外部キーが含まれ、各キーはエンティティ表の1つの主キーを指します。

    <cmp-field>および<cmr-field>要素はJavaデータ型を表すため、ユーザーが予想するデータベース型に変換されない場合があります。CMP型をデータベース型に変換するには一定の規則があります(「CMP型のデータベース型への変換」を参照)。Javaデータ型からデータベース・データ型への変換ルールは、J2EE_HOME/config/database-schemasディレクトリにある特定のデータベースXMLファイルで変更できます。このディレクトリにはすべてのデータベース・ファイルが含まれます。Oracleデータベース変換ファイルの名前はoracle.xmlです。

  • 主キー: エンティティBeanの基底表には主キーが含まれます(「主キーの構成」を参照)。主キーのタイプを次に示します。

    • 定義済主キー: 主キーは、単純なデータ型またはクラスとして<primkey-field>要素で指定されたとおりに生成されます。このため、列名は<primkey-field>要素の名前と同じになります。

    • 複合主キー: 主キーはクラス内で定義され、複数のフィールドで構成されます。複合主キー内の各フィールドはデータベース表の列で表されます。ここで各フィールドは表の主キーの一部であると想定されます。

    • 自動的に生成される主キー: <prim-key-class>要素でjava.lang.Objectを主キー・クラス型として指定する場合に、主キー名を<primkey-field>要素で指定しないと、主キーは自動的にコンテナで生成されます。列の名前はAUTOIDです。

CMP型のデータベース型への変換

<cmp-field>におけるコンテナ管理の永続フィールドと、主キー型を定義する際に、単純なデータ型とシリアライズ可能なJavaクラスを定義できます。

この項の内容は次のとおりです。

単純なデータ型

表5-4はサポートされている単純なデータ型(persistence-type属性で指定可能)の一覧と、これらの型のSQL型およびOracleデータベース型へのマッピングを示しています。これらのマッピングは、Oracle以外のデータベースでの動作が保証されていない点に注意してください。

表5-4 単純なデータ型

既知の型(ネイティブ) SQL型 Oracle型

java.lang.String

VARCHAR(255)

VARCHAR(255)

java.lang.Integer[]

INTEGER

NUMBER(20,0)

java.lang.Long[]

INTEGER

NUMBER(20,0)

java.lang.Short[]

INTEGER

NUMBER(10,0)

java.lang.Double[]

DOUBLE PRECISION

NUMBER(30,0)

java.lang.Float[]

FLOAT

NUMBER(20,5)

java.lang.Byte[]

SMALLINT

NUMBER(10,0)

java.lang.Character[]

CHAR

CHAR(1)

java.lang.Boolean[]

BIT

NUMBER(1,0)

java.util.Date

DATETIME

DATE

java.sql.Date

DATE

DATE

java.uti.Time

DATE

DATE

java.sql.Timestamp

TIMESTAMP

TIMESTAMP

java.lang.String

CLOB

CLOB

char[]

CLOB

CLOB

byte[]

BLOB

BLOB

java.io.Serializable(最大4KB)

LONGVARBINARY

BLOB



注意:

これらのデータ型のマッピングはconfig/database-schema/<db>.xml構成ファイルで変更できます。

DateTimeはデータベースのDATEにマップします。これはDATEに時間が含まれるためです。ただし、Timestampは、ナノ秒単位で時間を指定するデータベースのTIMESTAMPにマップします。

java.sql.CLOBおよびjava.sql.BLOBの直接マッピングは、これらのオブジェクトがシリアライズ可能ではないため現在はサポートされていません。ただし、Stringまたはchar[]およびbyte[]を、データベース列型のCLOBおよびBLOBにそれぞれマップできます。char[]CLOBへのマッピングまたはbyte[]BLOBへのマッピングは、Oracleデータベースでのみ可能です。Oracle JDBC APIはこの操作を取り扱うように変更されています。

シリアライズ済オブジェクトをシンJDBCドライバでBLOB型にマッピングする際には4KBの制限があります。

Stringおよびchar[]変数をデータベースのVARCHAR2にマップする際は、最大2KBまで保持できます。ただし、2KBを超えるStringオブジェクトまたはchar[]も、次の方法でCLOBにマップできます。

  1. Bean実装でStringまたはchar[]オブジェクトを使用します。

  2. <cmp-field-mapping>要素のpersistence-type属性が次のようにオブジェクトをCLOBとして定義します。

    <cmp-field-mapping name="stringdata" persistence-name="stringdata"
                                         persistence-type="CLOB" />
    
    

同様に、Bean実装のbyte[]BLOBに次のようにマップできます。

<cmp-field-mapping name="bytedata" persistence-name="bytedata"
                                   persistence-type="BLOB" />

シリアライズ可能クラス

単純なデータ型の他に、java.io.Serializableインタフェースを実装するユーザー・クラスを定義できます。これらのクラスはデータベースのBLOBに格納されます。

他のエンティティBeanまたはCollection

他のエンティティBeanまたはCollectionオブジェクトはCMP型として定義しないでください。これらは関連を示すため、関連フィールド内で次のように定義する必要があります。

  • 別のエンティティBeanとの関連は常に<cmr-field>関連で定義されます。

  • Collectionオブジェクトは関連の「多」側を形成し、<cmr-field>関連内で構成する必要があります。


    注意:

    Collectionのサブインタフェース(Listなど)は使用しないでください。かわりにCollectionを使用してください。

関連フィールドのデータベースに対する明示的マッピングの構成

「永続フィールドのデータベースに対するデフォルト・マッピングの構成」で説明したように、コンテナは関連フィールドをデータベース表に自動的にマップできます。OC4Jで提供されるデフォルトを使用しない場合、または既存のデータベース表にフィールドをマップする必要がある場合は、既存のデータベース表に対するエンティティBeanとorion-ejb-jar.xmlファイル内のその列との関連を手動でマップできます。


注意:

関連フィールドを明示的にマップするように、orion-ejb-jar.xmlファイルの<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)の各要素および属性を変更する必要があります。JDeveloper IDEにはエンティティBeanとデータベース表の間の複雑なマッピングを管理する機能があります。つまり、JDeveloperはデプロイメント・ディスクリプタを検証して非一貫性を防止します。ユーザーが自分でorion-ejb-jar.xmlファイルを変更することも可能ですが、コンテナ管理の関連の変更にはJDeveloperを使用することをお薦めします。JDeveloperの詳細は「JDeveloperの使用」を参照してください。

エンティティBeanのマッピングと既存データベースを手動で照合するには、orion-ejb-jar.xmlファイルを次の手順で変更します。

  1. orion-application.xmlファイルの<autocreate-tables>要素をfalseに設定して、コンテナ管理の永続性を持つエンティティBeanをデプロイします。

  2. application-deployments/ディレクトリからユーザーの開発ディレクトリにorion-ejb-jar.xmlファイルをコピーします。

  3. 正しいデータ・ソースを指すように<data-source>要素を変更します。互いに関連付けられているすべてのBeanが同じデータ・ソースを使用する必要がある点に注意してください。

  4. 正しい表を指し示すようにtable属性を変更します。これが<entity-deployments>要素で定義されているBeanに対する正しい表であることを確認してください。

  5. 各Beanの永続性タイプ(永続フィールドでも関連フィールドでも)に対する正しい列を指すようにpersistence-name属性を変更します。

  6. orion-application.xmlファイルの<autocreate-tables>要素をtrueに設定します。

  7. アプリケーションを再アーカイブしてから再デプロイします。

エンティティBeanのマッピングに照合する既存データベースがない場合に手動でマッピング要素を変更するには、次の手順に従います。

  1. orion-application.xmlファイルの<autocreate-tables>要素をfalseに設定し、ejb-jar.xml要素を構成してBeanをデプロイします。

    OC4Jはデフォルト・マッピングが含まれるorion-ejb-jar.xmlファイルを作成します。これらのフィールドは作成するよりも変更する方が簡単です。

  2. J2EE_HOME/application-deploymentsディレクトリからユーザーの開発環境に、コンテナが作成したorion-ejb-jar.xmlファイルをコピーします。

  3. 関連タイプに基づいてユーザーが指定したデータベース表および列を使用するように、orion-ejb-jar.xmlファイルの<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)を変更します。詳細は「データベース表とのBean関連をマップするためのorion-ejb-jar.xmlの構成」を参照してください。

  4. orion-application.xmlファイルの<autocreate-tables>要素をtrueに設定します。

  5. アプリケーションを再アーカイブしてから再デプロイします。


    注意:

    <autocreate-tables>falseに設定せずにアプリケーションをデプロイすると、OC4Jは自動的にデフォルト表を作成します。これらの表はすべて、アプリケーションを再デプロイする前に削除する必要があります。アソシエーション表がある場合はそれも削除します。

データベース表とのBean関連をマップするためのorion-ejb-jar.xmlの構成

エンティティBean間の関連はejb-jar.xmlファイルの<relationships>要素で定義されます。エンティティBeanとデータベース表および列の間のマッピングは、orion-ejb-jar.xmlファイルの<entity-deployment>要素で指定されます。

orion-ejb-jar.xmlファイルは、<cmp-field-mapping>要素内で、データベース表および列とのBeanの関連をマップします。単純な1対1関連についての<entity-deployment>および<cmp-field-mapping>要素のXML構造を次に示します。

<entity-deployment name="SourceBeanName" location="JNDIlocation"
                   table="TableName" data-source="DataSourceJNDIName">
...
    <cmp-field-mapping name="CMRfield_name">
        <entity-ref home="targetBeanName">
            <cmp-field-mapping name="CMRfield_name"
            persistence-name="targetBean_PKcolumn" />
        </entity-ref>
    </cmp-field-mapping>
...

<cmp-field-mapping>要素内で、Beanの名前(方向を示す関連のソース)、JNDIロケーション、情報を永続させるデータベース表を定義して、ejb-jar.xmlファイルで定義されたそれぞれの永続および関連フィールドを基底データベースにマップします。

<entity-deployment>要素の属性(表A-1「<entity-deployment>要素の属性」を参照)は、Beanについて次の項目を定義します。

  • name属性は、ejb-jar.xmlファイルの<ejb-name>要素で定義されたBeanのEJB名を指定します。このname属性は、Beanのejb-jar.xmlファイル定義とデータベースへのマッピングとを結び付けます。

  • location属性はBeanのJNDI名を指定します。

  • table属性はこのエンティティBeanがマップされる対象のデータベース表を指定します。

  • data-source属性は表が存在するデータベースを指定します。互いに相互作用するBean、または互いに関連付けられているBeanはすべて、データ・ソースが同じである必要があります。これには、同一アプリケーションのBean、同一トランザクションの一部であるBean、または親子関連にあるBeanが含まれます。

orion-ejb-jar.xmlファイルの<cmp-field-mapping>要素は次のフィールドをデータベース列にマップします。

  • ejb-jar.xmlファイルの<cmp-field>要素は永続フィールドを定義します。

  • ejb-jar.xmlファイルの<cmr-field>要素は関連フィールドを定義します。

例5-6 1対1関連におけるejb-jar.xmlとorion-ejb-jar.xmlのマッピング

例5-6は、ejb-jar.xmlファイルの<cmr-field>要素がどのようにorion-ejb-jar.xmlファイルの<cmp-field-mapping>要素にマップされるかを示しています。<cmp-field-mapping>name属性が2つのXMLファイル間のリンクを提供します。name属性は変更しないでください。

EJB-JAR.XML

<relationship-role-source>
    <ejb-name>EmpBean</ejb-name>
</relationship-role-source>
<cmr-field>
    <cmr-field-name>address</cmr-field-name>
</cmr-field>

ORION-EJB-JAR.XML

<cmp-field-mapping name="address">
    <entity-ref home="AddressBean">
        <cmp-field-mapping name="address" persistence-name="addressPK" />
    </entity-ref>
</cmp-field-mapping>

関連フィールドを完全に指定してマップするには、ネストされた<cmp-field-mapping>要素が使用されます。ネストの書式は関連のタイプによって異なります。ターゲットBeanの主キーであるデータベース列は、内部の<cmp-field-mapping>要素のpersistence-name属性で定義されます。既存のデータベースがある場合、列名を照合するには各<cmp-field-mapping>要素に対するpersistence-name属性を変更します。

明示的な1対1関連マッピング

仮説モデルでは、1人の従業員(EmpBeanで表される)とそのアドレス(AddressBeanで表される)の間に1対1の単方向の関連(「CMRの方向」を参照)があります。EmpBeanaddress関連フィールドを使用してAddressBeanを示します。これらの2つのBeanはEMPおよびADDRESSデータベース表にマップされます。EMP表には、ADDRESS表のAddressPKという主キーを示す、addressという外部キーがあります。

例5-7 明示的な1対1の単方向関連マッピング

Beanとその関連はejb-jar.xmlおよびorion-ejb-jar.xmlデプロイメント・ディスクリプタの両方で指定されます。例5-7が示すように、ejb-jar.xmlファイルでは、EmpBeanAddressBean間の1対1関連が<relationships>要素内で定義されます。方向(「CMRの方向」を参照)は1つまたは2つの<cmr-field>要素で指定されます。

Beanのデータベース永続記憶域へのマッピングはorion-ejb-jar.xmlファイルで定義されます。1対1関連は<cmp-field-mapping>要素内の<entity-ref>要素によって両側にマップされます。<entity-ref>は関連のターゲット・エンティティBeanを示します。

EJB-JAR.XML

<relationships>
...
    <ejb-relation>
    ...
    <multiplicity>One</multiplicity>
    <relationship-role-source>
        <ejb-name>EmpBean</ejb-name>
    </relationship-role-source>
    <cmr-field>
        <cmr-field-name>address</cmr-field-name>
    </cmr-field>
    ...
    </ejb-relation>
    <ejb-relation>
    ...
        <relationship-role-source>
            <ejb-name>AddressBean</ejb-name>
        </relationship-role-source>
        ...
    </ejb-relation>
...

ORION-EJB-JAR.XML

<entity-deployment name="EmpBean"...

    <cmp-field-mapping name="address">
        <entity-ref home="AddressBean">
            <cmp-field-mapping name="address" persistentce-name="addressPK" />
        </entity-ref>
    </cmp-field-mapping>
    ...
</entity-deployment>
<entity-deployment name="AddressBean"...
    ...
    <cmp-field-mapping name="empNumber">
        <entity-ref home="EmpBean">
            <cmp-field-mapping name="empNumber" persistentce-name="empnumber" />
        </entity-ref>
    </cmp-field-mapping>
    ...
</entity-deployment>

Beanフィールドを既存データベースにマップするには、orion-ejb-jar.xmlファイルの<cmp-field-mapping>要素内のフィールドを理解する必要があります。この要素の構造は次のとおりです。

<cmp-field-mapping name="CMRField_name">
    <entity-ref home="targetBeanName">
        <cmp-field-mapping name="CMRfield_name"
         persistence-name="targetBean_PKcolumn" />
    </entity-ref>
</cmp-field-mapping>

前述した構造の例では次のことが指定されています。

  • <cmp-field-mapping>要素のname属性は、ejb-jar.xmlファイルの<cmp-field>要素と同じです。<cmp-field-mapping>要素のname属性は変更しないでください。

  • ターゲットBean名が<entity-ref>要素のhome属性で指定されます。

  • ターゲットBeanの主キーであるデータベース列は、内部の<cmp-field-mapping>要素のpersistence-name属性で定義されます。既存のデータベースがある場合、列名を照合するには各<cmp-field-mapping>要素に対するpersistence-name属性を変更します。

明示的な1対多関連マッピング

仮説モデルでは、各従業員(EmpBeanで表される)は1つの部門(DeptBeanで表される)に所属し、各部門には複数の従業員がいる可能性があります。部門表には主キーがあります。従業員表には、各従業員を識別するための主キーと、従業員の部門を示すための外部キーがあります。1人の従業員の部門を探す場合、単純なSQL文で外部キーから部門情報を取り出します。ある部門のすべての従業員を探す場合は、コンテナで部門表および従業員表の両方にJOIN文を実行して、指定した部門番号のすべての従業員を取り出します。

これはデフォルトの動作です。他のデータベース表にマッピングを変更する必要がある場合は、JDeveloperを使用するか、orion-ejb-jar.xmlファイルを手動で変更して<collection-mapping>または<set-mapping>要素を操作します。


注意:

関連フィールドを明示的にマップするように、orion-ejb-jar.xmlファイルの<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)の各要素および属性を変更します。JDeveloperにはエンティティBeanとデータベース表の間の複雑なマッピングを管理する機能があります。JDeveloperはデプロイメント・ディスクリプタを検証して非一貫性を防止します。ユーザーが自分でorion-ejb-jar.xmlファイルを変更することも可能ですが、コンテナ管理の関連の変更にはJDeveloperを使用することをお薦めします。JDeveloperの詳細は「JDeveloperの使用」を参照してください。

例5-8 外部キーを使用した、明示的な1対多の双方向関連マッピング

例5-8は、多数の従業員がいる1つの部門の双方向関連におけるマッピングを示しています。関連の「1」側は部門で、関連の「多」側は従業員です。例5-8は、この関連で外部キーを使用するための、手動によるorion-ejb-jar.xmlファイルの変更を示しています。

EJB-JAR.XML

<relationships>
    <ejb-relation>
        <ejb-relation-name>Dept-Emps</ejb-relation-name>
        <ejb-relationship-role>
            <ejb-relationship-role-name>Dept-has-Emps</ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source>
                <ejb-name>DeptBean</ejb-name>
            </relationship-role-source>
            <cmr-field>
                <cmr-field-name>employees</cmr-field-name>
                <cmr-field-type>java.util.Set</cmr-field-type>
            </cmr-field>
        </ejb-relationship-role>
           <ejb-relationship-role-name>Emps-have-Dept</ejb-relationship-role-name>
            <multiplicity>Many</multiplicity>
            <cascade-delete/>
            <relationship-role-source>
                <ejb-name>EmpBean</ejb-name>
            </relationship-role-source>
            <cmr-field>
                <cmr-field-name>dept</cmr-field-name>
            </cmr-field>
        </ejb-relationship-role>
    </ejb-relation>
</relationships>

ORION-EJB-JAR.XML

<enterprise-beans>
    <entity-deployment name="DeptBean" data-source="jdbc/scottDS" table="DEPT">
        <primkey-mapping>
            <cmp-field-mapping name="deptno" persistence-name="DEPTNO" />  /*PK*/
        </primkey-mapping>
        <cmp-field-mapping name="dname" persistence-name="DNAME" />
        <cmp-field-mapping name="employees">
        /*points from DEPTNO column in EMP to DEPTNO in DEPT*/
1.      <collection-mapping table="EMP"> /*table with FK*/
            <primkey-mapping>
                <cmp-field-mapping name="DeptBean_deptno"> /*CMR field name*/
                    <entity-ref home="DeptBean"> /*points to DeptBean*/
2.                      <cmp-field-mapping name="DeptBean_deptno"
                        persistence-name="EDEPTNO"/>
                    </entity-ref>
                </cmp-field-mapping>
            </primkey-mapping>
            <value-mapping type="mypackage1.EmpLocal">
                <cmp-field-mapping name="EmpBean_empnumber">
                    <entity-ref home="EmpBean">
                        <cmp-field-mapping name="EmpBean_empnumber"
                        persistence-name="EMPNUMBER"/>
                    </entity-ref>
                </cmp-field-mapping>
            </value-mapping>
        </collection-mapping>
        </cmp-field-mapping>
    </entity-deployment>
    <entity-deployment name="EmpBean" data-source="jdbc/scottDS" table="EMP">
        <primkey-mapping>
            <cmp-field-mapping name="empNumber" persistence-name="EMPNUMBER"/>
        </primkey-mapping>
        <cmp-field-mapping name="empName" persistence-name="ENAME" />
        <cmp-field-mapping name="salary" persistence-name="SAL" />
        <cmp-field-mapping name="dept"> /*foreign key*/ 
            <entity-ref home="DeptBean">
2.              <cmp-field-mapping name="dept" persistence-name="EDEPTNO" />
            </entity-ref>
        </cmp-field-mapping>
    </entity-deployment>
</enterprise-beans>

前述したorion-ejb-jar.xmlの例では、「1」関連(部門)の<collection-mapping>または<set-mapping>要素で識別された表が、ターゲットBeanの表(employee Bean表)の名前である場合、1対多関連は外部キーで定義されます。たとえば、部門定義のtable属性はEMPです。

外部キーは「多」関連のデータベース表で定義されます。前述した例では、EDEPTNO外部キー列はEMPデータベース表に存在します。これはEmpBean構成における<cmp-field-mapping>要素のpersistence-name属性で定義されます。

このため、orion-ejb-jar.xmlファイルの<collection-mapping>または<set-mapping>要素を操作するには、「1」エンティティBean(Collectionを含む)に対する<entity-deployment>要素(表A-1「<entity-deployment>要素の属性」を参照)を次のように変更します。

  1. 「1」関連における<collection-mapping>または<set-mapping>表属性の表が、「多」関連のデータベース表になるように変更します。この例では、この属性がEMP表となるように変更します。

  2. 「多」関連構成内で「1」関連を示す外部キーを変更します。この例では、persistence-name属性でEDEPTNO外部キーを指定するように<cmp-field-mapping>要素を変更します。

データベース分離レベルの構成

特定のBeanに対してデータベース分離レベル(「エンティティBeanのデータベース分離レベルとリソース競合」を参照)の1つを構成できます。つまり、Beanがトランザクションを開始したときに、このBeanに対するデータベース分離レベルがOC4J固有のデプロイメント・ディスクリプタで(パラレル実行またはデータ整合性において)指定されているレベルになるように指定できます。


注意:

一度設定すると、Beanに対する分離レベルはトランザクション全体に対して有効です。

<entity-deployment>要素のisolation属性(表A-1「<entity-deployment>要素の属性」を参照)で各エンティティBeanに対する分離レベルを設定できます。committedまたはserializableの値を使用できます。デフォルトはcommittedです。このデフォルト値をserializableに変更するには、orion-ejb-jar.xmlで対象のBeanを次のように構成します。

<entity-deployment ...  isolation="serializable"
 ...
</entity-deployment>

serializable分離レベルはデータ整合性を提供し、committed分離レベルはパラレル実行を有効にします。


警告:

エミュレートされていないデータ・ソースを使用中の場合は、分離レベルをserializableに設定しないでください。この設定を使用すると、エミュレートされていないデータ・ソースは機能しません。



警告:

OC4J固有のデプロイメント・ディスクリプタにおける<max-tx-retries>要素の値が0(デフォルトは0)よりも大きい場合、serializableレベルでは更新の紛失が起こる可能性があります。この要素が0よりも大きい値に設定されている場合、2番目のブロックされたクライアントがORA-8177例外を受け取ると、コンテナは更新を再試行します。ロックされていない行が再試行によって検出され、更新が行われます。これによって2番目のクライアントの更新が成功し、1番目のクライアントの更新を上書きします。serializable分離レベルを使用する場合は、データ整合性のため<max-tx-retries>要素を0にしておくことを考慮してください。


分離レベルを定義しない場合、ユーザーはデータベースで構成されているレベルを受け取ります。OC4J固有のデプロイメント・ディスクリプタ内で分離レベルを設定すると、このBeanに対するグローバル・トランザクションのライフ・サイクル間は、データベースの構成済の分離レベルが一時的にオーバーライドされます。つまり、serializableレベルを使用するようにBeanを定義する場合、トランザクションが終了するまでの間のみ、OC4JではこのBeanに対してデータベースが強制的にserializableとなります。

組合せがリソース競合の結果に影響する場合は、エンティティBeanの並行性モードとデータベース分離レベルの両方を指定することができます。詳細は「エンティティBeanのデータベース分離レベルと並行性モードの組合せ」を参照してください。

リソース競合の詳細は、「データベース・リソースの競合の回避」を参照してください。

並行性モードの構成

並行性モードでは、リソース競合管理のためいつ遮断するか、またはいつパラレル実行を行うかを決定します。詳細は「エンティティBeanの並行性モードとリソース競合」を参照してください。

コンテナ管理の永続性を持つエンティティBeanの並行性モードを設定するには、適切な並行性の値(pessimisticoptimisticまたはread-only)を、OC4J固有デプロイメント・ディスクリプタ(orion-ejb-jar.xmlファイル)の<entity-deployment>要素のlocking-mode属性(表A-1「<entity-deployment>要素の属性」を参照)に追加します。デフォルトの並行性モードはoptimisticです。並行性モードをpessimisticに変更するには、次の変更を実行します。

<entity-deployment ...  locking-mode="pessimistic"
 ...
</entity-deployment>

並行性モードはBeanごとに定義され、ロックの効果はトランザクション境界に適用されます。

パラレル実行には、ラッパーおよびBeanインスタンスに対するプール・サイズの正しい設定が必要です。

詳細は次のトピックを参照してください。

データベースへの排他的書込みアクセスの構成

<entity-deployment>要素のexclusive-write-access属性(表A-1「<entity-deployment>要素の属性」を参照)は、これがデータベース内の表にアクセスする唯一のエンティティBeanであり、リソースの更新に外部メソッドが使用されないことを示しています。これは、このBeanに対して保持されたキャッシュがすべてこのBeanによってのみ使用されることをOC4Jインスタンスに伝えます。基本的には、この属性をtrueに設定すると、これがこのBean内で使用された表を更新する唯一のBeanであることがコンテナで保証されます。このため、Beanに対して保持されたキャッシュを、バックエンド・データベースから定期的に更新する必要はありません。

このフラグによって、ユーザーによる表の更新が妨げられることはありません。つまり、実際には表はロックされません。ただし、表を手動で更新した場合、または別のBeanから更新した場合、その結果はこのBean内で自動的に更新されません。

exclusive-write-access属性のデフォルト値はfalseです。エンティティBeanの並行性モードの効果(「並行性モードの構成」を参照)によって、read-onlyエンティティBeanについてのみこの要素をtrueに設定できます。OC4Jでは、pessimisticおよびoptimistic並行性モードについてはこの属性を常にfalseにリセットします。

詳細は次のトピックを参照してください。

コンテナ管理の永続性を持つEJB 2.0エンティティBeanに対するコールバック・メソッドの構成

エンティティBeanクラス(「エンティティBeanクラスの実装」を参照)で、エンティティBeanのコールバック・メソッド(「コールバック・メソッド」を参照)の次の構成を指定する必要があります。

他のコールバック・メソッドには、エンティティBeanクラスの空の実装のみが必要です。コンテナはこれらのメソッドに対して完全な実装を提供します。ただし、ユーザーのエンティティBean実装のロジックによっては、次の作業に類似した作業を行う場合があります。