4.4. 動的モデル
注記
以下の機能は現在実験段階にあり、 近い将来変更される可能性があります。
必ずしも永続エンティティを実行時に POJO クラスや JavaBean オブジェクトとして表現する必要はありません。 Hibernate は動的モデル (実行時に
Map
の Map
を使用) や 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
に設定した後、実行時に Map
の Map
を使用することができます。
Session s = openSession(); Transaction tx = s.beginTransaction(); // 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();
動的マッピングの主な利点の1つとして、エンティティクラスの実装を必要としないにも拘らず、プロトタイピングのターンアラウンドタイム(TAT)が短い点が挙げられます。しかし、 コンパイル時の型チェックがないため、 実行時に多くの例外に対処することになります。 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 接続やトランザクション、 その他のコンテキスト情報を共有します。 そのため、 セカンダリ Session
上で flush()
や close()
を呼び出す必要がなく、 トランザクションや接続の処理をプライマリの作業単位に委ねることができます。
XML 表現の能力についての詳細は 18章XML マッピング を参照してください。