Hibernate.org Community Documentation

- Précédent
- Suivant

## Chapitre 20. Mappage XML

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

## 20.1. Travailler avec des données XML

Hibernate vous laisse travailler avec des données XML persistantes de la même manière que vous travaillez avec des POJO persistants. Un arbre XML peut être vu comme une autre manière de représenter les données relationnelles au niveau objet, à la place des POJO.

Hibernate supporte dom4j en tant qu'API pour la manipulation des arbres XML. Vous pouvez écrire des requêtes qui récupèrent des arbres dom4j à partir de la base de données, et avoir toutes les modifications que vous faites sur l'arbre automatiquement synchronisées dans la base de données. Vous pouvez même prendre un document XML, l'analyser en utilisant dom4j, et l'écrire dans la base de données via les opérations basiques de Hibernate : `persist(), saveOrUpdate(), merge(), delete(), replicate()` (merge n'est pas encore supporté).

Cette fonctionnalité a plusieurs applications dont l'import/export de données, l'externalisation de données d'entités via JMS ou SOAP et les rapports XSLT.

Un simple mappage peut être utilisé pour simultanément mapper les propriétés d'une classe et les noeuds d'un document XML vers la base de données, ou, s'il n'y a pas de classe à mapper, il peut être utilisé juste pour mapper le XML.

### 20.1.1. Spécifier le mappage XML et le mappage d'une classe ensemble

Voici un exemple de mappage d'un POJO et du XML simultanément :

    <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. Spécifier seulement un mappage XML

Voici un exemple dans lequel il n'y a pas de classe 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

    >

Ce mappage vous permet d'accéder aux données comme un arbre dom4j, ou comme un graphe de paire nom/valeur de propriété (`Map` s java). Les noms des propriétés sont des constructions purement logiques qui peuvent être référées dans des requêtes HQL.

## 20.2. Métadonnées du mappage XML

Plusieurs éléments du mappage Hibernate acceptent l'attribut `node`. Ceci vous permet de spécifier le nom d'un attribut XML ou d'un élément qui contient la propriété ou les données de l'entité. Le format de l'attribut `node` doit être un des suivants :

- `"element-name"` - mappe vers l'élément XML nommé

- `"@attribute-name"` - mappe vers l'attribut XML nommé

- `"."` - mappe vers le parent de l'élément

- `"element-name/@attribute-name"` - mappe vers l'élément nommé de l'attribut nommé

Pour des collections et de simples associations valuées, il y a un attribut `embed-xml` supplémentaire. Si `embed-xml="true"`, qui est la valeur par défaut, l'arbre XML pour l'entité associée (ou la collection des types de valeurs) sera embarquée directement dans l'arbre XML pour l'entité qui possède l'association. Sinon, si `embed-xml="false"`, alors seule la valeur de l'identifiant référencé apparaîtra dans le XML pour de simples associations de points, et les collections n'apparaîtront pas.

Faire attention à ne pas laisser `embed-xml="true"` pour trop d'associations, puisque XML ne traite pas bien les liens circulaires.

    <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

    >

Dans ce cas, nous avons décidé d'embarquer la collection d'identifiants de compte, mais pas les données actuelles du compte. La requête HQL suivante :

    from Customer c left join fetch c.accounts where c.lastName like :lastName

devrait retourner l'ensemble de données suivant :

    <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

    >

Si vous positionnez `embed-xml="true"` sur le mappage `<one-to-many>`, les données ressembleraient à ce qui suit :

    <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. Manipuler des données XML

Relisons et mettons à jour des documents XML dans l'application. Nous effectuons cela en obtenant une session 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();

Il est extrêmement utile de combiner cette fonctionnalité avec l'opération `replicate()` de Hibernate pour implémenter des imports/exports de données XML.

Copyright © 2004 Red Hat, Inc.

- PrécédentChapitre 19. Filtrer les données
- Niveau supérieur
- Sommaire
- SuivantChapitre 21. Améliorer les performances