Hibernate.org Community Documentation

- Anterior
- Siguiente

## Capítulo 20. Mapeo XML

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

## 20.1. Trabajo con datos XML

Hibernate le permite trabajar con datos XML persistentes en casi de la misma forma que trabaja con POJOs persistentes. Un árbol XML analizado semáticamente se puede considerar como otra manera de representar los datos relacionales a nivel de objetos, en lugar de POJOs.

Hibernate soporta dom4j como API para manipular árboles XML. Puede escribir consultas que recuperen árboles dom4j de la base de datos y puede tener cualquier modificación que realice al árbol sincronizada automáticamente con la base de datos. Incluso puede tomar un documento XML, analizarlo sintácticamente utilizando dom4j, y escribirlo a la base de datos con cualquiera de las operaciones básicas de Hibernate: `persist(), saveOrUpdate(), merge(), delete(), replicate()` (merge aún no está soportado).

Esta funcionalidad tiene muchas aplicaciones incluyendo la importación/exportación de datos, externalización de datos de entidad por medio de JMS o SOAP y reportes basados en XSLT.

Un sólo mapeo se puede utilizar para mapear simultáneamente las propiedades de una clase y los nodos de un documento XML a la base de datos, o si no hay ninguna clase a mapear, se puede utilizar para mapear sólo el XML.

### 20.1.1. Especificación de los mapeos de XML y de clase en conjunto

Este es un ejemplo del mapeo de un POJO y XML de manera simultánea:

    <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. Especificación de sólo un mapeo XML

Este es un ejemplo donde no hay ninguna clase 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

    >

Este mapeo le permite acceder a los datos como un árbol dom4j o como un grafo de parejas nombre/valor de propiedad o`Map`as de Java. Los nombres de propiedades son construcciones puramente lógicas a las que se puede hacer referencia en consultas HQL.

## 20.2. Mapeo de metadatos XML

Muchos elementos de mapeo de Hibernate aceptan el atributo `node`. Esto le permite especificar el nombre de un atributo o elemento XML que contenga los datos de la propiedad o entidad. El formato del atributo `node` tiene que ser uno de los siguientes:

- `"element-name"` - mapea al elemento XML mencionado

- `"@attribute-name"`: mapea al atributo XML mencionado

- `"."` - mapea al elemento padre

- `"element-name/@attribute-name"`: mapea al atributo mencionado del elemento nombrado

Para las colecciones y asociaciones monovaluadas, existe un atributo adicional `embed-xml`. Si `embed-xml="true"`, el cual es el valor por defecto, el árbol XML para la entidad asociada (o colección de tipo de valor) será incluida directamente en el árbol XML para la entidad que posee la asociación. De otra manera, si `embed-xml="false"`, entonces sólo el valor identificador referenciado aparecerá en el XML para asociaciones de punto único y para las colecciones simplemente no aparecerá.

No deje `embed-xml="true"` para demasiadas asociaciones ya que XML no se ocupa bien de la circularidad.

    <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

    >

En este caso, la colección de ids de cuenta están incluídos, pero no los datos reales de cuenta. La siguiente consulta HQL:

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

retornaría conjuntos de datos como este:

    <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 establece `embed-xml="true"` en el mapeo `<one-to-many>`, puede que los datos se vean así:

    <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. Manipulación de datos XML

Puede releer y actualizar documentos XML en la aplicación. Puede hacer esto obteniendo una sesión 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();

Es útil combinar esta funcionalidad con la operación `replicate()` de Hibernate para implementar la importación/exportación de datos basada en XML.

Copyright © 2004 Red Hat, Inc.

- AnteriorCapítulo 19. Filtración de datos
- Subir
- Inicio
- SiguienteCapítulo 21. Mejoramiento del rendimiento