4.4. 動的モデル

4.4. 動的モデル

以下の機能は現在実験段階にあると見なされており、近い将来変更される可能性があることに注意してください。

永続エンティティは、必ずしも実行時に POJO クラスや JavaBean オブジェクトで表現する必要はありません。 Hibernate は(実行時に MapMap を使う)動的モデルと、 DOM4J ツリーとしてのエンティティの表現もサポートします。このアプローチを使うと永続クラスを書かず、マッピングファイルだけを書くことになります。

デフォルトでは、 Hibernate は通常の POJO モードで動作します。 default_entity_mode 設定オプションを使って、特定の SessionFactory に対するデフォルトのエンティティ表現モードを設定することができます (表 3.3. 「Hibernate 設定プロパティ」 を見てください)。

以下の例では Map を使った表現を紹介します。まずマッピングファイルで、クラス名の代わりに(またはそれに加えて) entity-name を定義しなければなりません:

<hibernate-mapping>

    <class entity-name="Customer">

        <id name="id"
            type="long"
            column="ID">
            <generator class="sequence"/>
        </id>

        <property name="name"
            column="NAME"
            type="string"/>

        <property name="address"
            column="ADDRESS"
            type="string"/>

        <many-to-one name="organization"
            column="ORGANIZATION_ID"
            class="Organization"/>

        <bag name="orders"
            inverse="true"
            lazy="false"
            cascade="all">
            <key column="CUSTOMER_ID"/>
            <one-to-many class="Order"/>
        </bag>

    </class>
    
</hibernate-mapping>

関連がターゲットのクラス名を使って定義していたとしても、関連のターゲット型も POJO ではなく動的なエンティティでも構わないことに注意してください。

SessionFactory に対してデフォルトのエンティティモードを dynamic-map に設定した後、実行時に MapMap を使うことができます:

Session s = openSession();
Transaction tx = s.beginTransaction();
Session s = openSession();

// Create a customer
Map david = new HashMap();
david.put("name", "David");

// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");

// Link both
david.put("organization", foobar);

// Save both
s.save("Customer", david);
s.save("Organization", foobar);

tx.commit();
s.close();

動的なマッピングの利点は、エンティティクラスの実装を必要としないため、プロトタイピングに要するターンアラウンドタイムが早いということです。しかしコンパイル時の型チェックがないので、実行時に非常に多くの例外処理を扱わなければならないでしょう。 Hibernate マッピングのおかげで、データベーススキーマは容易に正規化でき、健全になり、後で適切なドメインモデルの実装を追加することが可能になります。

エンティティ表現モードは Session ごとに設定することも可能です。

Session dynamicSession = pojoSession.getSession(EntityMode.MAP);

// Create a customer
Map david = new HashMap();
david.put("name", "David");
dynamicSession.save("Customer", david);
...
dynamicSession.flush();
dynamicSession.close()
...
// Continue on pojoSession

EntityMode を使った getSession() の呼び出しは SessionFactory ではなく Session APIにあることに注意してください。その方法では、新しい Session は、ベースとなる JDBC コネクション、トランザクション、その他のコンテキスト情報を共有します。これは2番目の Session では flush()close() を呼ぶ必要がないということ、そのためトランザクションとコネクションの管理を1番目の作業単位(Unit of Work)に任せることができるということです。

XML 表現の能力についてのさらなる情報は 章 18. XML マッピング に記述されています。