Hibernate.org Community Documentation
XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active development.
Hibernate 使得你可以用 XML 数据来进行工作,恰如你用持久化的 POJO 进行工作那样。解析过的 XML 树 可以被认为是代替 POJO 的另外一种在对象层面上表示关系型数据的途径。
Hibernate 支持采用 dom4j 作为操作 XML 树的 API。你可以写一些查询从数据库中检索出 dom4j 树,随后你对这颗树做的任何修改都将自动同步回数据库。你甚至可以用 dom4j 解析 一篇 XML 文档,然后使用 Hibernate 的任一基本操作将它写入数据库:persist(),saveOrUpdate(),merge(),delete(),replicate()
(合并操作merge()目前还不支持)。
这一特性可以应用在很多场合,包括数据导入导出,通过 JMS 或 SOAP 具体化实体数据以及 基于 XSLT 的报表。
一个单一的映射就可以将类的属性和 XML 文档的节点同时映射到数据库。如果不需要映射类,它也可以用来只映射 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
>
这是一个不映射 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 查询中引用它。
许多 Hibernate 映射元素具有 node
属性。这使你可以指定用来保存 属性或实体数据的 XML 属性或元素。node
属性必须是下列格式之一:
-
"element-name"
:映射为指定的 XML 元素 -
"@attribute-name"
:映射为指定的 XML 属性 -
"."
:映射为父元素 -
"element-name/@attribute-name"
:映射为指定元素的指定属性
对于集合和单值的关联,有一个额外的 embed-xml
属性可用。这个属性的缺省值是真(embed-xml="true"
)。如果 embed-xml="true"
,则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的 XML 树中。否则,如果 embed-xml="false"
,那么对于单值的关联,仅被引用的实体的标识符出现在 XML 树中(被引用实体本身不出现),而集合则根本不出现。
你应该小心,不要让太多关联的 embed-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 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 属性置为真(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
>
你也可以重新读入和更新应用程序中的 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();
将这一特色与 Hibernate 的 replicate()
操作结合起来对于实现的基于 XML 的数据导入/导出将非常有用。
版权 © 2004 Red Hat, Inc.