Hibernate.orgCommunity Documentation
XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active development.
Hibernate では永続性の POJO を使って作業するのとほぼ同じようなやり方で、永続性の XML データを使って作業できます。解析された XML ツリーは POJO の代わりにオブジェクトレベルで関係データを表わす別の方法であるとみなされています。
Hibernate は XML ツリーを操作するための API として dom4j をサポートしています。データベースから dom4j のツリーを復元するクエリを書くことができ、ツリーに対して行った修正は自動的にデータベースと同期されます。また XML ドキュメントを取得することができ、 dom4j を使ってドキュメントをパースし、 Hibernate の任意の基本操作を使ってデータベースへ書き込むことができます。: つまり、 persist(), saveOrUpdate(), merge(), delete(), replicate()
操作です (マージはまだサポートしていません)。
データのインポート/エクスポート、 JMS によるエンティティデータの外部化や SOAP 、 XSLT ベースのレポートなど、この機能には多くの用途があります。
単一のマッピングは、クラスのプロパティと XML ドキュメントのノードを同時にデータベースへマッピングするために使うことができます。またマッピングするクラスがなければ、 XML だけをマッピングするために使うことができます。
これは POJO と XML を同時にマッピングする例です:
<class name="Account"
table="ACCOUNTS"
node="account">
<id name="accountId"
column="ACCOUNT_ID"
node="@id"/>
<many-to-one name="customer"
column="CUSTOMER_ID"
node="customer/@id"
embed-xml="false"/>
<property name="balance"
column="BALANCE"
node="balance"/>
...
</class
>
これは POJO クラスがないマッピングの例です:
<class entity-name="Account"
table="ACCOUNTS"
node="account">
<id name="id"
column="ACCOUNT_ID"
node="@id"
type="string"/>
<many-to-one name="customerId"
column="CUSTOMER_ID"
node="customer/@id"
embed-xml="false"
entity-name="Customer"/>
<property name="balance"
column="BALANCE"
node="balance"
type="big_decimal"/>
...
</class
>
このマッピングにより、 dom4j ツリーか、プロパティ名/値の組のグラフ(java の Map
)としてデータにアクセスできます。プロパティの名前は、 HQL クエリ内で参照できる純粋な論理構造です。
多くの Hibernate のマッピング要素は node
属性が使用できます。これにより XML 属性の名前やプロパティやエンティティデータを保持する要素を指定できます。 node
属性のフォーマットは以下の中の1つでなければなりません:
"element-name"
- 指定した XML 要素へマッピングします
"@attribute-name"
- 指定した XML 属性へマッピングします
"."
- 親要素へマッピングします
"element-name/@attribute-name"
- 指定したエレメントの指定した属性へマッピングします
コレクションと単一の値の関連に対して、おまけの embed-xml
属性があります。デフォルトの embed-xml="true"
と設定した場合、関連するエンティティ (値型のコレクション) の XML ツリーは、直接関連を所有するエンティティの XML ツリー内に埋め込まれます。反対に、 embed-xml="false"
と設定した場合、参照される識別子の値だけが多重度1側の関連に対する XML に現れ、単純にコレクションはまったく現れなくなります。
あまりに多くの関連に対して embed-xml="true"
としたままにするのは注意すべきです。 XML は循環をうまく扱えません。
<class name="Customer"
table="CUSTOMER"
node="customer">
<id name="id"
column="CUST_ID"
node="@id"/>
<map name="accounts"
node="."
embed-xml="true">
<key column="CUSTOMER_ID"
not-null="true"/>
<map-key column="SHORT_DESC"
node="@short-desc"
type="string"/>
<one-to-many entity-name="Account"
embed-xml="false"
node="account"/>
</map>
<component name="name"
node="name">
<property name="firstName"
node="first-name"/>
<property name="initial"
node="initial"/>
<property name="lastName"
node="last-name"/>
</component>
...
</class
>
この例では、実際の account のデータではなく、 account の id のコレクションを埋め込むことにしました。続きの HQL クエリです:
from Customer c left join fetch c.accounts where c.lastName like :lastName
このようなデータセットを返すでしょう:
<customer id="123456789">
<account short-desc="Savings"
>987632567</account>
<account short-desc="Credit Card"
>985612323</account>
<name>
<first-name
>Gavin</first-name>
<initial
>A</initial>
<last-name
>King</last-name>
</name>
...
</customer
>
<one-to-many>
マッピングで embed-xml="true"
と設定した場合、データはこのようになるでしょう。
<customer id="123456789">
<account id="987632567" short-desc="Savings">
<customer id="123456789"/>
<balance
>100.29</balance>
</account>
<account id="985612323" short-desc="Credit Card">
<customer id="123456789"/>
<balance
>-2370.34</balance>
</account>
<name>
<first-name
>Gavin</first-name>
<initial
>A</initial>
<last-name
>King</last-name>
</name>
...
</customer
>
XML ドキュメントを、アプリケーション内で再読み込みや更新をしてみましょう。以下では dom4j のセッションを取得することで行います:
Document doc = ....;
Session session = factory.openSession();
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Transaction tx = session.beginTransaction();
List results = dom4jSession
.createQuery("from Customer c left join fetch c.accounts where c.lastName like :lastName")
.list();
for ( int i=0; i<results.size(); i++ ) {
//add the customer data to the XML document
Element customer = (Element) results.get(i);
doc.add(customer);
}
tx.commit();
session.close();
Session session = factory.openSession();
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Transaction tx = session.beginTransaction();
Element cust = (Element) dom4jSession.get("Customer", customerId);
for ( int i=0; i<results.size(); i++ ) {
Element customer = (Element) results.get(i);
//change the customer name in the XML and database
Element name = customer.element("name");
name.element("first-name").setText(firstName);
name.element("initial").setText(initial);
name.element("last-name").setText(lastName);
}
tx.commit();
session.close();
XML ベースのデータのインポート/エクスポートを実装するために、 Hibernate の replicate()
操作をこの機能に結びつけるのは極めて有効です。
製作著作 © 2004 Red Hat, Inc.