Hibernate.org Community Documentation

- 前のページ
- 次のページ

## 第20章 XML マッピング

XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active development.

## 20.1. XML データでの作業

Hibernate では永続性の POJO を使って作業するのとほぼ同じようなやり方で、永続性の XML データを使って作業できます。解析された XML ツリーは POJO の代わりにオブジェクトレベルで関係データを表わす別の方法であるとみなされています。

Hibernate は XML ツリーを操作するための API として dom4j をサポートしています。データベースから dom4j のツリーを復元するクエリを書くことができ、ツリーに対して行った修正は自動的にデータベースと同期されます。また XML ドキュメントを取得することができ、 dom4j を使ってドキュメントをパースし、 Hibernate の任意の基本操作を使ってデータベースへ書き込むことができます。： つまり、 `persist(), saveOrUpdate(), merge(), delete(), replicate()` 操作です (マージはまだサポートしていません)。

データのインポート/エクスポート、 JMS によるエンティティデータの外部化や SOAP 、 XSLT ベースのレポートなど、この機能には多くの用途があります。

単一のマッピングは、クラスのプロパティと XML ドキュメントのノードを同時にデータベースへマッピングするために使うことができます。またマッピングするクラスがなければ、 XML だけをマッピングするために使うことができます。

### 20.1.1. 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

    >

### 20.1.2. XML マッピングだけを指定する

これは 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 クエリ内で参照できる純粋な論理構造です。

## 20.2. XML マッピングのメタデータ

多くの 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"` と設定した場合、参照される識別子の値だけが多重度１側の関連に対する 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

    >

## 20.3. XML データを扱う

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.

- 前のページ第19章 データのフィルタリング
- 上に戻る
- ホーム
- 次のページ第21章 パフォーマンスの改善