hibernate-orm/reference/zh-cn/modules/xml.xml

271 lines
9.1 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<chapter id="xml">
<title>XML映射</title>
<para><emphasis>
注意这是Hibernate 3.0的一个实验性的特性。这一特性仍在积极开发中。
</emphasis></para>
<sect1 id="xml-intro" revision="1">
<title>用XML数据进行工作</title>
<para>
Hibernate使得你可以用XML数据来进行工作恰如你用持久化的POJO进行工作那样。解析过的XML树
可以被认为是另外一种在对象层面上代替POJO来表示关系型数据的途径.
</para>
<para>
Hibernate支持采用dom4j作为操作XML树的API。你可以写一个查询从数据库中检索出
dom4j树随后你对这颗树做的任何修改都将自动同步回数据库。你甚至可以用dom4j解析
一篇XML文档然后使用Hibernate的任一基本操作将它写入数据库
<literal>persist(), saveOrUpdate(), merge(), delete(), replicate()</literal>
(合并操作merge()目前还不支持)。
</para>
<para>
这一特性可以应用在很多场合包括数据导入导出通过JMS或SOAP表现实体数据以及
基于XSLT的报表。
</para>
<para>
一个单一的映射就可以将类的属性和XML文档的节点同时映射到数据库。如果不需要映射类
它也可以用来只映射XML文档。
</para>
<sect2 id="xml-intro-mapping">
<title>指定同时映射XML和类</title>
<para>
这是一个同时映射POJO和XML的例子
</para>
<programlisting><![CDATA[<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>]]></programlisting>
</sect2>
<sect2 id="xml-onlyxml">
<title>只定义XML映射</title>
<para>
这是一个不映射POJO的例子
</para>
<programlisting><![CDATA[<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>]]></programlisting>
<para>
这个映射使得你既可以把数据作为一棵dom4j树那样访问又可以作为由属性键值对(java <literal>Map</literal>s)
组成的图那样访问。属性名字是纯粹逻辑上的结构你可以在HQL查询中引用它。
</para>
</sect2>
</sect1>
<sect1 id="xml-mapping" revision="1">
<title>XML映射元数据</title>
<para>
许多Hibernate映射元素具有<literal>node</literal>属性。这使你可以指定用来保存
属性或实体数据的XML属性或元素。<literal>node</literal>属性必须是下列格式之一:
</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>"element-name"</literal> - 映射为指定的XML元素</para>
</listitem>
<listitem>
<para><literal>"@attribute-name"</literal> - 映射为指定的XML属性</para>
</listitem>
<listitem>
<para><literal>"."</literal> - 映射为父元素</para>
</listitem>
<listitem>
<para>
<literal>"element-name/@attribute-name"</literal> -
映射为指定元素的指定属性
</para>
</listitem>
</itemizedlist>
<para>
对于集合和单值的关联,有一个额外的<literal>embed-xml</literal>属性可用。
这个属性的缺省值是真(<literal>embed-xml="true"</literal>)。如果<literal>embed-xml="true"</literal>
则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中。
否则,如果<literal>embed-xml="false"</literal>,那么对于单值的关联,仅被引用的实体的标识符出现在
XML树中(被引用实体本身不出现),而集合则根本不出现。
</para>
<para>
你应该小心不要让太多关联的embed-xml属性为真(<literal>embed-xml="true"</literal>)因为XML不能很好地处理
循环引用!
</para>
<programlisting><![CDATA[<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>]]></programlisting>
<para>
在这个例子中,我们决定嵌入帐目号码(account id)的集合但不嵌入实际的帐目数据。下面的HQL查询
</para>
<programlisting><![CDATA[from Customer c left join fetch c.accounts where c.lastName like :lastName]]></programlisting>
<para>
返回的数据集将是这样:
</para>
<programlisting><![CDATA[<customer id="123456789">
<account id="987632567" short-desc="Savings"/>
<account id="985612323" short-desc="Credit Card"/>
<name>
<first-name>Gavin</first-name>
<initial>A</initial>
<last-name>King</last-name>
</name>
...
</customer>]]></programlisting>
<para>
如果你把一对多映射<literal>&lt;one-to-many&gt;</literal>的embed-xml属性置为真(<literal>embed-xml="true"</literal>)
则数据看上去就像这样:
</para>
<programlisting><![CDATA[<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>]]></programlisting>
</sect1>
<sect1 id="xml-manipulation" revision="1">
<title>操作XML数据</title>
<para>
让我们来读入和更新应用程序中的XML文档。通过获取一个dom4j会话可以做到这一点
</para>
<programlisting><![CDATA[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();]]></programlisting>
<programlisting><![CDATA[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();]]></programlisting>
<para>
将这一特色与Hibernate的<literal>replicate()</literal>操作结合起来而实现的基于XML的数据导入/导出将非常有用.
</para>
</sect1>
</chapter>