Hibernate.org Community Documentation

- Anterior
- Próxima

## Capítulo 20. Mapeamento XML

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

## 20.1. Trabalhando com dados em XML

O Hibernate permite que se trabalhe com dados persistentes em XML quase da mesma maneira como você trabalha com POJOs persistentes. Uma árvore XML analisada, pode ser considerada como apenas uma maneira de representar os dados relacionais como objetos, ao invés dos POJOs.

O Hibernate suporta a API dom4j para manipular árvores XML. Você pode escrever queries que retornem árvores dom4j do banco de dados e automaticamente sincronizar com o banco de dados qualquer modificação feita nessas árvores. Você pode até mesmo pegar um documento XML, analisá-lo usando o dom4j, e escrever as alterações no banco de dados usando quaisquer operações básicas do Hibernate: `persist(), saveOrUpdate(),merge(), delete(), replicate()` (a mesclagem ainda não é suportada)

Essa funcionalidade tem várias aplicações incluindo importação/exportação de dados, externalização de dados de entidade via JMS or SOAP e relatórios usando XSLT.

Um mapeamento simples pode ser usado para simultaneamente mapear propriedades da classe e nós de um documento XML para um banco de dados ou, se não houver classe para mapear, pode ser usado simplesmente para mapear o XML.

### 20.1.1. Especificando o mapeamento de uma classe e de um arquivo XML simultaneamente

Segue um exemplo de como mapear um POJO e um XML ao mesmo tempo:

    <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. Especificando somente um mapeamento XML

Segue um exemplo que não contém uma 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

    >

Esse mapeamento permite que você acesse os dados como uma árvore dom4j ou um gráfico de pares de nome/valor de propriedade ou `Map`s do Java. Os nomes de propriedades são somente construções lógicas que podem ser referenciadas em consultas HQL.

## 20.2. Mapeando metadados com XML

Muitos elementos do mapeamento do Hibernate aceitam a função `node`. Através dele, você pode especificar o nome de uma função ou elemento XML que contenha a propriedade ou os dados da entidade. O formato da função `node` deve ser o seguinte:

- `"element-name"`: mapeia para o elemento XML nomeado

- `"@attribute-name"`: mapeia para a função XML com determinado nome

- `"."`: mapeia para o elemento pai

- `"element-name/@attribute-name"`: mapeia para a função nomeada com o elemento nomeado

Para coleções e associações de valores simples, existe uma função adicional `embed-xml`. Se a função `embed-xml="true"`, que é o valor padrão, a árvore XML para a entidade associada (ou coleção de determinado tipo de valor) será embutida diretamente na árvore XML que contém a associação. Por outro lado, se `embed-xml="false"`, então apenas o valor do identificador referenciado irá aparecer no XML para associações simples e as coleções simplesmente não irão aparecer.

Você precisa tomar cuidado para não deixar o `embed-xml="true"` para muitas associações, pois o XML não suporta bem referências circulares.

    <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

    >

Nesse caso, decidimos incorporar a coleção de ids de contas, e não os dados de contas. Segue a abaixo a consulta HQL:

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

Retornaria um conjunto de dados como esse:

    <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

    >

Se você ajustar `embed-xml="true"` em um mapeamento `<one-to-many>`, os dados se pareceriam com o seguinte:

    <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. Manipulando dados em XML

Vamos reler e atualizar documentos em XML em nossa aplicação. Nós fazemos isso obtendo uma sessão do 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();

É extremamente útil combinar essa funcionalidade com a operação `replicate()` do Hibernate para implementar importação/exportação de dados baseados em XML.

Copyright © 2004 Red Hat, Inc.

- AnteriorCapítulo 19. Filtrando dados
- Acima
- Principal
- PróximaCapítulo 21. Aumentando o desempenho