Hibernate.orgCommunity Documentation
XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active development.
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.
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
>
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 oMap
as de Java. Los nombres de propiedades son construcciones puramente lógicas a las que se puede hacer referencia en consultas HQL.
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
>
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.