﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-JAVA流通桥-文章分类-castor问题</title><link>http://www.blogjava.net/zhuyan/category/20907.html</link><description>JAVA启发者</description><language>zh-cn</language><lastBuildDate>Sat, 24 Mar 2007 18:31:34 GMT</lastBuildDate><pubDate>Sat, 24 Mar 2007 18:31:34 GMT</pubDate><ttl>60</ttl><item><title>用 Castor 进行数据绑定</title><link>http://www.blogjava.net/zhuyan/articles/105944.html</link><dc:creator>朱岩</dc:creator><author>朱岩</author><pubDate>Fri, 23 Mar 2007 09:52:00 GMT</pubDate><guid>http://www.blogjava.net/zhuyan/articles/105944.html</guid><wfw:comment>http://www.blogjava.net/zhuyan/comments/105944.html</wfw:comment><comments>http://www.blogjava.net/zhuyan/articles/105944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhuyan/comments/commentRss/105944.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhuyan/services/trackbacks/105944.html</trackback:ping><description><![CDATA[
		<blockquote>对于主要关心文档数据内容的应用程序，Java XML 数据绑定是一种代替 XML 文档模型的强大机制。本文中，企业 Java 专家 Dennis Sosnoski 介绍数据绑定，并讨论什么使它如此令人瞩目。然后，他向读者展示了如何利用 Java 数据绑定的开放源代码 Castor 框架来处理日益复杂的文档。如果您的应用程序更多的把 XML 作为数据而不是文档，您就会愿意了解这种处理 XML 和 Java 技术的简单有效的方法。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>应用程序中使用 XML 文档的多数方法都把重点放在 XML 上：从 XML 的观点使用文档，按照 XML 元素、属性和字符数据内容编程。如果应用程序主要关心文档的 XML 结构，那么这种方法非常好。对于更关心文档中所含数据而非文档本身的许多应用程序而言， <i>数据绑定</i>提供了一种更简单的使用 XML 的方法。 </p>
		<p>
				<a name="h1">
						<span class="atitle">文档模型与数据绑定</span>
				</a>
		</p>
		<p>本系列文章的上一篇（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources"><font color="#996699">参考资料</font></a>）所讨论的文档模型，是与数据绑定最接近的替代方案。文档模型和数据绑定都在内存中建立文档的表示，都需要在内部表示和标准文本 XML 之间双向转换。两者的区别在于文档模型尽可能保持 XML 结构，而数据绑定只关心应用程序所使用的文档数据。 </p>
		<p>为了说明这一点，图 1 给出了一个简单 XML 文档的数据模型视图。文档成分——在这个例子中只有元素和文本节点——通过反映原始 XML 文档的结构连接在一起。形成的节点树很容易和原始文档联系，但要解释树中表示的实际数据就不那么容易了。</p>
		<br />
		<br />
		<a name="figure1">
				<b>图 1. 文档的文档模型视图</b>
		</a>
		<br />
		<img height="220" alt="文档的文档模型视图" src="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/document-model.gif" width="600" />
		<br />
		<p>如果应用程序使用 XML 文档模型方法，您就需要处理这种类型的树。这种情况下，您将使用节点之间的父子关系在树的上下层之间导航，使用属于同一父节点的子女之间的兄弟关系在树的同一层中导航。您可以非常详尽地处理树结构，当把树序列化为文本时，生成的 XML 文档将反映您所做的修改（比如插入的注释）。</p>
		<p>现在来看看与图 1 截然不同的图 2，它表示同一文档的数据绑定视图。在这里，转换过程几乎隐藏了原始 XML 文档的所有结构，但是因为只有通过两个对象，更容易看清楚真正的数据，也更很容易访问这些数据。</p>
		<br />
		<br />
		<a name="figure2">
				<b>图 2. 文档的数据绑定视图</b>
		</a>
		<br />
		<img height="220" alt="文档的数据绑定视图" src="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/data-binding.gif" width="566" />
		<br />
		<p>使用这种数据结构就像是一般的 Java 编程——甚至根本不需要知道 XML！（哦，还是不要走得 <i>太</i>远了——我们这些专家顾问还得活……）您的项目中至少要有人明白，这种数据结构和 XML 文档之间的映射是如何建立的，但这仍然是向简化迈出的一大步。 </p>
		<p>不 <i>仅仅</i>是编程的简化，数据绑定还带来其他的好处。与文档模型方法相比，因为抽掉了许多文档细节，数据绑定通常需要的内存更少。比如前面两个图中所示的数据结构：文档模型方法使用了 10 个单独的对象，与此相比数据绑定只使用了两个。要创建的东西少，构造文档的数据绑定表示可能就更快一些。最后，数据绑定与文档模型相比，应用程序可以更快地访问数据，因为您可以控制如何表示和存储数据。我后面还要讲到这一点。 </p>
		<p>既然数据绑定那么好，为何还要使用文档模型呢？以下两种情况需要使用文档模型：</p>
		<ul>
				<li>应用程序真正关注文档结构的细节。比方说，如果您在编写一个 XML 文档编辑器，您就会坚持使用文档模型而非数据绑定。 
</li>
				<li>您处理的文档没有固定的结构。比如实现一种通用的 XML 文档数据库，数据绑定就不是一种好办法。 </li>
		</ul>
		<p>许多应用程序使用 XML 传输数据，但并不关心文档表示的细节。这类应用程序非常适合使用数据绑定。如果您的应用程序符合这种模式，请继续读下去。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h2">
						<span class="atitle">Castor 框架</span>
				</a>
		</p>
		<p>目前有几种不同的框架支持 Java XML 数据绑定，但还没有标准的接口。这种情况最终会得到改变：Java Community Process (JCP) 的 JSR-031 正在努力定义这方面的标准（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources"><font color="#996699">参考资料</font></a>）。现在让我们选择一个框架并学习使用它的接口。 </p>
		<p>本文选择了 Castor 数据绑定框架。Castor 项目采用 BSD 类型的证书，因此可在任何类型的应用程序（包括完整版权的项目）中使用。 Castor 实际上仅仅有 XML 数据绑定，它还支持 SQL 和 LDAP 绑定，尽管本文中不讨论这些其他的特性。该项目从 2000 年初开始发起，目前处于后 beta 状态（一般可以使用这个版本，但是如果需要问题修正，您可能需要升级到目前的 CVS 版本）。请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources"><font color="#996699">参考资料</font></a>部分的 Castor 站点链接，以了解更多的细节并下载该软件。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h3">
						<span class="atitle">默认绑定</span>
				</a>
		</p>
		<p>Castor XML 数据绑定很容易上手，甚至不需要定义 XML 文档格式。只要您的数据用类 JavaBean 的对象表示，Castor 就能自动生成表示这些数据的文档格式，然后从文档重构原始数据。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N100BB">
																				<b>数据绑定词汇表</b>
																		</a>
																		<br />
																		<p>下面这个小小的词汇表列出了本文中要用到的一些术语：</p>
																		<p>
																				<i>编组</i>是在内存中生成对象的 XML 表示的过程。与 Java 序列化一样，这种表示需要包括所有依赖的对象：主对象引用的对象、这些对象引用的其他对象、等等。 </p>
																		<p>
																				<i>解组</i>是上述过程的逆过程，在内存中从 XML 表示创建对象（以及依赖的对象）。 </p>
																		<p>
																				<i>映射</i>是用于编组和解组的一些规则。Castor 有一些内建的规则定义了默认映射，本文这一部分将要描述。它也允许您使用单独的映射文件，参见后述。 </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>那么“类 JavaBean”是什么意思呢？真正的 JavaBean 是可视化组件，可以在开发环境中配置以用于 GUI 布局。一些源于真正 JavaBean 的惯例已经被 Java 团体普遍接受，特别是对于数据类。如果一个类符合以下惯例，我就称之为是“类 JavaBean”的： </p>
		<ul>
				<li>这个类是公共的 
</li>
				<li>定义了公共的默认（没有参数）构造函数 
</li>
				<li>定义了公共的 <code>getX</code> 和 <code>setX</code> 方法访问属性（数据）值 </li>
		</ul>
		<p>关于技术定义已经扯得太远了，当提到这些类 JavaBean 类时，我将不再重复说明，只是称之为“bean”类。</p>
		<p>在整篇文章中，我将使用航线班机时刻表作为示例代码。我们从一个简单的 bean 类开始说明它的工作原理，这个类表示一个特定的航班，包括四个信息项：</p>
		<ul>
				<li>飞机编号（航空公司） 
</li>
				<li>航班编号 
</li>
				<li>起飞时间 
</li>
				<li>抵达时间 </li>
		</ul>
		<p>下面的清单 1 给出了处理航班信息的代码。</p>
		<br />
		<br />
		<a name="code1">
				<b>清单 1. 航班信息 bean</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public class FlightBean
{
private String m_carrier;
private int m_number;
private String m_departure;
private String m_arrival;
public FlightBean() {}
public void setCarrier(String carrier) {
m_carrier = carrier;
}
public String getCarrier() {
return m_carrier;
}
public void setNumber(int number) {
m_number = number;
}
public int getNumber() {
return m_number;
}
public void setDepartureTime(String time) {
m_departure = time;
}
public String getDepartureTime() {
return m_departure;
}
public void setArrivalTime(String time) {
m_arrival = time;
}
public String getArrivalTime() {
return m_arrival;
}
}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您可以看到，这个 bean 本身没有什么意思，因此我想增加一个类并在默认的 XML 绑定中使用它，如清单 2 所示。</p>
		<br />
		<br />
		<a name="code2">
				<b>清单 2. 测试默认的数据绑定</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import java.io.*;
import org.exolab.castor.xml.*;
public class Test
{
public static void main(String[] argv) {
// build a test bean
FlightBean bean = new FlightBean();
bean.setCarrier("AR");
bean.setNumber(426);
bean.setDepartureTime("6:23a");
bean.setArrivalTime("8:42a");
try {
// write it out as XML
File file = new File("test.xml");
Writer writer = new FileWriter(file);
Marshaller.marshal(bean, writer);
// now restore the value and list what we get
Reader reader = new FileReader(file);
FlightBean read = (FlightBean)
Unmarshaller.unmarshal(FlightBean.class, reader);
System.out.println("Flight " + read.getCarrier() +
read.getNumber() + " departing at " +
read.getDepartureTime() +
" and arriving at " + read.getArrivalTime());
} catch (IOException ex) {
ex.printStackTrace(System.err);
} catch (MarshalException ex) {
ex.printStackTrace(System.err);
} catch (ValidationException ex) {
ex.printStackTrace(System.err);
}
}
}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N1011F">
																				<b>Castor 不仅能用于 bean</b>
																		</a>
																		<br />
																		<p>实际上，Castor 不仅仅能用于本文所述的类 JavaBean 类。它也可以访问带有公共成员变量的简单数据对象类的数据。比如，稍微改动前述的 <code>Test</code> 类，您就可以对航班数据使用如下的定义，并最终得到同样的 XML 格式： </p>
																		<table cellspacing="0" cellpadding="0" width="100%" border="0">
																				<tbody>
																						<tr>
																								<td class="code-outline">
																										<pre class="displaycode">public class FlightData
{
public String carrier;
public int number;
public String departure;
public String arrival;
}</pre>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<br />
																		<p>为了使 Castor 正常工作，一个类必须全部采用这种方式或那种方式。如果类定义了 <i>任何</i><code>getX</code> 或 <code>setX</code> 方法，Castor 就将其视作 bean，并在编组和解组时只使用这些方法。 </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>这段代码首先构造了一个 <code>FlightBean</code> bean，并使用一些固定的数据初始化它。然后用该 bean 默认的 Castor XML 映射将其写入一个输出文件。最后又读回生成的 XML， 同样使用默认映射重构 bean，然后打印重构的 bean 中的信息。结果如下： </p>
		<p>
				<code>Flight AR426 departing at 6:23a and arriving at 8:42a</code>
		</p>
		<p>这个输出结果表明您已经成功地来回转换了航班信息（不算太糟，只有两次方法调用）。现在我还不满足于简单控制台输出，准备再往深处挖一挖。</p>
		<p>
				<a name="h4">
						<span class="smalltitle">
								<strong>
										<font face="Arial">幕后</font>
								</strong>
						</span>
				</a>
		</p>
		<p>为了更清楚地了解这个例子中发生了什么，看一看 <code>Marshaller.marshal()</code> 调用生成的 XML。文档如下： </p>
		<table cellspacing="0" cellpadding="0" width="65%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;flight-bean number="426"&gt;
&lt;arrival-time&gt;8:42a&lt;/arrival-time&gt;
&lt;departure-time&gt;6:23a&lt;/departure-time&gt;
&lt;carrier&gt;AR&lt;/carrier&gt;
&lt;/flight-bean&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Castor 使用 Java 内部检查机制检查 <code>Marshaller.marshal()</code> 调用传递的对象。在本例中，它发现了定义的四个属性值。Castor 在输出的 XML 中创建一个元素（文档的根元素）表示整个对象。元素名从对象的类名中衍生出来，在这里是 <code>flight-bean</code> 。然后Castor 用以下两种方法中的一个，把该对象的属性值包括进来： </p>
		<ul>
				<li>对于具有基本类型值的属性创建元素的一个属性（本例中只有 <code>number</code> 属性通过 <code>getNumber()</code> 方法公开为 <code>int</code> 值）。 
</li>
				<li>对于每个具有对象类型值的属性创建根元素的一个子元素（本例中的所有其他属性，因为它们是字符串）。 </li>
		</ul>
		<p>
		</p>
		<p>结果就是上面所示的 XML 文档。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h5">
						<span class="atitle">改变 XML 格式</span>
				</a>
		</p>
		<p>如果不喜欢 Castor 的默认映射格式，您可以方便地改变映射。在我们的航班信息例子中，比方说，假定我们需要更紧凑的数据表示。使用属性代替子元素有助于实现这个目标，我们也许还希望使用比默认的名字更短一些的名字。如下所示的文档就可以很好地满足我们的需要：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="h6">
						<span class="smalltitle">
								<strong>
										<font face="Arial">定义映射</font>
								</strong>
						</span>
				</a>
		</p>
		<p>为了让 Castor 使用这种格式而非默认的格式，首先需要定义描述这种格式的映射。映射描述本身（非常意外的）是一个 XML 文档。清单 3 给出了把 bean 编组成上述格式的映射。</p>
		<br />
		<br />
		<a name="code3">
				<b>清单 3. 紧凑格式的映射</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
"-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.exolab.org/mapping.dtd"&gt;
&lt;mapping&gt;
&lt;description&gt;Basic mapping example&lt;/description&gt;
&lt;class name="FlightBean" auto-complete="true"&gt;
&lt;map-to xml="flight"/&gt;
&lt;field name="carrier"&gt;
&lt;bind-xml name="carrier" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="departureTime"&gt;
&lt;bind-xml name="depart" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="arrivalTime"&gt;
&lt;bind-xml name="arrive" node="attribute"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;/mapping&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<code>class</code> 元素定义了一个命名类 <code>FlightBean</code> 的映射。通过在该元素中加入 <code>auto-complete</code> 属性并把值设为 <code>true</code> ，您可以告诉 Castor 对于该类的任何属性，只要没有在这个元素中专门列出，就使用默认映射。这样非常简便，因为 <code>number</code> 属性已经按照希望的方式处理了。 </p>
		<p>子元素 <code>map-to</code> 告诉 Castor，要把 <code>FlightBean</code> 类的实例映射为 XML 文档中的 <code>flight</code> 元素。如果您继续使用默认的元素名 <code>flight-bean</code> （参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#h4"><font color="#996699">幕后</font></a>小节中默认映射输出的例子），可以不使用该元素。 </p>
		<p>最后，对于每个希望以非默认方式处理的属性，可以引入一个 <code>field</code> 子元素。这些子元素都按照相同的模式： <code>name</code> 属性给出映射的属性名， <code>bind-xml</code> 子元素告诉 Castor 如何映射那个属性。这里要求把每个属性映射成给定名称的属性。 </p>
		<p>
				<a name="h7">
						<span class="smalltitle">
								<strong>
										<font face="Arial">使用映射</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现在已经定义了一个映射，您需要告诉 Castor 框架在编组和解组数据时使用那个映射。清单 4 说明了要实现这一点，需要对前面的代码做哪些修改。</p>
		<br />
		<br />
		<a name="code4">
				<b>清单 4. 使用映射编组和解组</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">...
// write it out as XML (if not already present)
Mapping map = new Mapping();
map.loadMapping("mapping.xml");
File file = new File("test.xml");
Writer writer = new FileWriter(file);
Marshaller marshaller = new Marshaller(writer);
marshaller.setMapping(map);
marshaller.marshal(bean);
// now restore the value and list what we get
Reader reader = new FileReader(file);
Unmarshaller unmarshaller = new Unmarshaller(map);
FlightBean read = (FlightBean)unmarshaller.unmarshal(reader);
...
} catch (MappingException ex) {
ex.printStackTrace(System.err);
...
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>与前面 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code2"><font color="#996699">清单 2</font></a>默认映射所用的代码相比，这段代码稍微复杂一点。在执行任何其他操作之前，首先要创建一个 <code>Mapping</code> 对象载入您的映射定义。真正的编组和解组也有区别。为了使用这个映射，您需要创建 <code>Marshaller</code> 和 <code>Unmarshaller</code> 对象，用定义的映射配置它们，调用这些对象的方法，而不是像第一个例子那样使用静态方法。最后，您必须提供对映射错误产生的另一个异常类型的处理。 </p>
		<p>完成这些修改后，您可以尝试再次运行程序。控制台输出与第一个例子相同（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code2"><font color="#996699">清单 2</font></a>所示），但是现在的 XML 文档看起来符合我们的需要： </p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h8">
						<span class="atitle">处理集合</span>
				</a>
		</p>
		<p>现在单个航班数据已经有了我们喜欢的形式，您可以定义一个更高级的结构：航线数据。这个结构包括起降机场的标识符以及在该航线上飞行的一组航班。清单 5 给出了一个包含这些信息的 bean 类的例子。</p>
		<br />
		<br />
		<a name="code5">
				<b>清单 5. 航线信息 bean</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import java.util.ArrayList;
public class RouteBean
{
private String m_from;
private String m_to;
private ArrayList m_flights;
public RouteBean() {
m_flights = new ArrayList();
}
public void setFrom(String from) {
m_from = from;
}
public String getFrom() {
return m_from;
}
public void setTo(String to) {
m_to = to;
}
public String getTo() {
return m_to;
}
public ArrayList getFlights() {
return m_flights;
}
public void addFlight(FlightBean flight) {
m_flights.add(flight);
}
}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在这段代码中，我定义了一个 <code>addFlight()</code> 方法，用于每次增加一个属于这条航线的航班。这是在测试程序中建立这种数据结构非常简便的办法，但是可能和您预料的相反， Castor 在解组时并不使用种方法向航线中增加航班。相反，它使用 <code>getFlights()</code> 方法访问一组航班，然后直接添加到集合中。 </p>
		<p>在映射中处理航班集合只需要稍微改变上一个例子（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code3"><font color="#996699">清单 3</font></a>所示）中的 <code>field</code> 元素。清单 6 显示了修改后的映射文件。 </p>
		<br />
		<br />
		<a name="code6">
				<b>清单 6. 映射包含一组航班的航线</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
"-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.exolab.org/mapping.dtd"&gt;
&lt;mapping&gt;
&lt;description&gt;Collection mapping example&lt;/description&gt;
&lt;class name="RouteBean"&gt;
&lt;map-to xml="route"/&gt;
&lt;field name="from"&gt;
&lt;bind-xml name="from" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="to"&gt;
&lt;bind-xml name="to" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="flights" collection="collection" type="FlightBean"&gt;
&lt;bind-xml name="flight"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;class name="FlightBean" auto-complete="true"&gt;
&lt;field name="carrier"&gt;
&lt;bind-xml name="carrier" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="departureTime"&gt;
&lt;bind-xml name="depart" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="arrivalTime"&gt;
&lt;bind-xml name="arrive" node="attribute"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;/mapping&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>一切都和上一个映射（如 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code3"><font color="#996699">清单 3</font></a>所示）完全相同，只不过用 <code>field</code> 元素定义了一个 <code>RouteBean</code> 的 <code>flights</code> 属性。这个映射用到了两个原来不需要的属性。 <code>collection</code> 属性的值 <code>collection</code> 把该属性定义成一个 java.util.Collection （其他值分别定义数组，java.util.Vectors 等等）。 <code>type</code> 属性定义包含在集合中的对象类型，值是完整的限定类名。这里的值是 <code>FlightBean</code> ，因为对这些类我没有使用包。 </p>
		<p>另一个区别在 <code>FlightBean</code> 类元素中，不再需要使用 <code>map-to</code> 子元素定义绑定的元素名。定义 <code>RouteBean</code> 的 <code>flights</code> 属性的 <code>field</code> 元素，通过它的 <code>bind-xml</code> 子元素定义了这一点。因为编组或解组 <code>FlightBean</code> 对象只能通过该属性，它们将永远使用这个 <code>bind-xml</code> 元素设定的名称。 </p>
		<p>我不再详细列出这个例子的测试程序，因为数据绑定部分和上一个例子相同。以下是用一些示例数据生成的 XML 文档：</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;route from="SEA" to="LAX"&gt;
&lt;flight carrier="AR" depart="6:23a" arrive="8:42a"
number="426"/&gt;
&lt;flight carrier="CA" depart="8:10a" arrive="10:52a"
number="833"/&gt;
&lt;flight carrier="AR" depart="9:00a" arrive="11:36a"
number="433"/&gt;
&lt;/route&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h9">
						<span class="atitle">对象引用</span>
				</a>
		</p>
		<p>现在可以为处理完整的航班时刻表做最后的准备了。您还需要增加三个 bean： </p>
		<ul>
				<li>
						<code>AirportBean</code> 用于用于机场信息 
</li>
				<li>
						<code>CarrierBean</code> 用于航线信息 
</li>
				<li>
						<code>TimeTableBean</code> 把一切组合起来 </li>
		</ul>
		<p>为了保持趣味性，除了上一个例子（参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#h8"><font color="#996699">处理集合</font></a>）中用到的 <code>RouteBean</code> 和 <code>FlightBean</code> 之间的从属关系，您还要在 bean 之间增加一些联系。 </p>
		<p>
				<a name="h10">
						<span class="smalltitle">
								<strong>
										<font face="Arial">连接 bean</font>
								</strong>
						</span>
				</a>
		</p>
		<p>要增加的第一个联系是修改 <code>FlightBean</code> ，让它直接引用班机信息，而不再仅仅用代码标识班机。以下是对 <code>FlightBean</code> 的修改： </p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public class FlightBean
{
private CarrierBean m_carrier;
...
public void setCarrier(CarrierBean carrier) {
m_carrier = carrier;
}
public CarrierBean getCarrier() {
return m_carrier;
}
...
}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>然后对 <code>RouteBean</code> 做同样的修改，让它引用机场信息： </p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public class RouteBean
{
private AirportBean m_from;
private AirportBean m_to;
...
public void setFrom(AirportBean from) {
m_from = from;
}
public AirportBean getFrom() {
return m_from;
}
public void setTo(AirportBean to) {
m_to = to;
}
public AirportBean getTo() {
return m_to;
}
...
}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>我没有给出新增 bean 自身的代码，因为和前面的代码相比没有什么新鲜的东西。您可以从下载文件 code.jar 中找到完整的示例代码（请参阅 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources"><font color="#996699">参考资料</font></a>）。 </p>
		<p>
				<a name="h11">
						<span class="smalltitle">
								<strong>
										<font face="Arial">映射引用</font>
								</strong>
						</span>
				</a>
		</p>
		<p>您可能需要映射文档的其他一些特性，以支持编组和解组的对象之间的引用。清单 7 给出了一个完整的映射：</p>
		<br />
		<br />
		<a name="code7">
				<b>清单 7. 完整的时刻表映射</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;!DOCTYPE databases PUBLIC
"-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.exolab.org/mapping.dtd"&gt;
&lt;mapping&gt;
&lt;description&gt;Reference mapping example&lt;/description&gt;
&lt;class name="TimeTableBean"&gt;
&lt;map-to xml="timetable"/&gt;
&lt;field name="carriers" type="CarrierBean" collection="collection"&gt;
&lt;bind-xml name="carrier"/&gt;
&lt;/field&gt;
&lt;field name="airports" type="AirportBean" collection="collection"&gt;
&lt;bind-xml name="airport"/&gt;
&lt;/field&gt;
&lt;field name="routes" type="RouteBean" collection="collection"&gt;
&lt;bind-xml name="route"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;class name="CarrierBean" identity="ident" auto-complete="true"&gt;
&lt;field name="ident"&gt;
&lt;bind-xml name="ident" node="attribute"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;class name="AirportBean" identity="ident" auto-complete="true"&gt;
&lt;field name="ident"&gt;
&lt;bind-xml name="ident" node="attribute"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;class name="RouteBean"&gt;
&lt;field name="from" type="AirportBean"&gt;
&lt;bind-xml name="from" node="attribute" reference="true"/&gt;
&lt;/field&gt;
&lt;field name="to" type="AirportBean"&gt;
&lt;bind-xml name="to" node="attribute" reference="true"/&gt;
&lt;/field&gt;
&lt;field name="flights" type="FlightBean" collection="collection"&gt;
&lt;bind-xml name="flight"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;class name="FlightBean" auto-complete="true"&gt;
&lt;field name="carrier"&gt;
&lt;bind-xml name="carrier" node="attribute" reference="true"/&gt;
&lt;/field&gt;
&lt;field name="departureTime"&gt;
&lt;bind-xml name="depart" node="attribute"/&gt;
&lt;/field&gt;
&lt;field name="arrivalTime"&gt;
&lt;bind-xml name="arrive" node="attribute"/&gt;
&lt;/field&gt;
&lt;/class&gt;
&lt;/mapping&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>除了新增的 bean 之外，这里有一个重要的变化，就是增加了 <code>identity</code> 和 <code>reference</code> 属性。 <code>class</code> 元素的 <code>identity</code> 属性，通知 Castor 这个命名属性是该类实例的唯一标识符。在这里，我把 <code>CarrierBean</code> 和 <code>AirportBean</code> 的 <code>ident</code> 属性定义成它们的标识符。 </p>
		<p>
				<code>bind-xml</code> 元素的 <code>reference</code> 属性，提供了对于该映射 Castor 所需要的另一部分链接信息。 <code>reference</code> 设为 <code>true</code> 的映射告诉 Castor 编组和解组引用对象的标识符，而不是对象本身的副本。从 <code>RouteBean</code> 链接 <code>AirportBean</code> （表示航线的起止点）的引用，从 <code>FlightBean</code> 链接 <code>CarrierBean</code> 的引用，都使用了这种方法。 </p>
		<p>当 Castor 使用这种类型的映射解组数据时，它自动把对象标识符转化为对实际对象的引用。您需要保证标识符的值确实是唯一的，甚至不同类型的对象之间也要保证这种唯一性。对于本例中的数据，这一点不成问题：飞机的标识符是两个字符，而机场的标识符是三个字符，永远不会冲突。如果 <i>确实</i>有潜在冲突的可能性，只要在所代表的对象类型的每个标识符加上唯一的前缀，就可以很容易地避免这种问题。 </p>
		<p>
				<a name="h12">
						<span class="smalltitle">
								<strong>
										<font face="Arial">编组后的时刻表</font>
								</strong>
						</span>
				</a>
		</p>
		<p>这个例子的测试代码没有新东西，只是增加了一些示例数据。清单 8 给出了编组形成的 XML 文档：</p>
		<br />
		<br />
		<a name="code8">
				<b>清单 8. 编组的时刻表</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&lt;?xml version="1.0"?&gt;
&lt;timetable&gt;
&lt;carrier ident="AR" rating="9"&gt;
&lt;URL&gt;http://www.arcticairlines.com&lt;/URL&gt;
&lt;name&gt;Arctic Airlines&lt;/name&gt;
&lt;/carrier&gt;
&lt;carrier ident="CA" rating="7"&gt;
&lt;URL&gt;http://www.combinedlines.com&lt;/URL&gt;
&lt;name&gt;Combined Airlines&lt;/name&gt;
&lt;/carrier&gt;
&lt;airport ident="SEA"&gt;
&lt;location&gt;Seattle, WA&lt;/location&gt;
&lt;name&gt;Seattle-Tacoma International Airport&lt;/name&gt;
&lt;/airport&gt;
&lt;airport ident="LAX"&gt;
&lt;location&gt;Los Angeles, CA&lt;/location&gt;
&lt;name&gt;Los Angeles International Airport&lt;/name&gt;
&lt;/airport&gt;
&lt;route from="SEA" to="LAX"&gt;
&lt;flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/&gt;
&lt;flight carrier="CA" depart="8:10a" arrive="10:52a" number="833"/&gt;
&lt;flight carrier="AR" depart="9:00a" arrive="11:36a" number="433"/&gt;
&lt;/route&gt;
&lt;route from="LAX" to="SEA"&gt;
&lt;flight carrier="CA" depart="7:45a" arrive="10:20a" number="311"/&gt;
&lt;flight carrier="AR" depart="9:27a" arrive="12:04p" number="593"/&gt;
&lt;flight carrier="AR" depart="12:30p" arrive="3:07p" number="102"/&gt;
&lt;/route&gt;
&lt;/timetable&gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h13">
						<span class="atitle">使用数据</span>
				</a>
		</p>
		<p>现在，时刻表中的所有数据都最终完成了，简单地看一看如何在程序中处理它们。使用数据绑定，您已经建立了时刻表的数据结构，它由几种类型的 bean 组成。处理数据的应用程序代码可以直接使用这些 bean。</p>
		<p>比方说，假设您要查看在西雅图和洛杉矶之间有哪些航班可供选择，并且要求班机至少具备指定的最低品质评价级别。清单 9 给出了使用数据绑定 bean 结构获取这些信息的基本代码（完整的细节请参阅从 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#resources"><font color="#996699">参考资料</font></a>下载的源文件）。 </p>
		<br />
		<br />
		<a name="code9">
				<b>清单 9. 航班查找程序代码</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">private static void listFlights(TimeTableBean top, String from,
String to, int rating) {
// find the routes for outbound and inbound flights
Iterator r_iter = top.getRoutes().iterator();
RouteBean in = null;
RouteBean out = null;
while (r_iter.hasNext()) {
RouteBean route = (RouteBean)r_iter.next();
if (route.getFrom().getIdent().equals(from) &amp;&amp;
route.getTo().getIdent().equals(to)) {
out = route;
} else if (route.getFrom().getIdent().equals(to) &amp;&amp;
route.getTo().getIdent().equals(from)) {
in = route;
}
}
// make sure we found the routes
if (in != null &amp;&amp; out != null) {
// find outbound flights meeting carrier rating requirement
Iterator o_iter = out.getFlights().iterator();
while (o_iter.hasNext()) {
FlightBean o_flight = (FlightBean)o_iter.next();
if (o_flight.getCarrier().getRating() &gt;= rating) {
// find inbound flights meeting carrier rating
//  requirement, and leaving after outbound arrives
int time = timeToMinute(o_flight.getArrivalTime());
Iterator i_iter = in.getFlights().iterator();
while (i_iter.hasNext()) {
FlightBean i_flight = (FlightBean)i_iter.next();
if (i_flight.getCarrier().getRating() &gt;= rating
&amp;&amp;
timeToMinute(i_flight.getDepartureTime())
&gt; time) {
// list the flight combination
printFlights(o_flight, i_flight, from, to);
}
}
}
}
}
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您可以尝试使用前面 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code8"><font color="#996699">清单 8</font></a>中的数据。如果您询问从西雅图（SEA）到洛杉矶（LAX）、级别大于或等于 8 的班机，就会得到如下的结果： </p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">Leave SEA on Arctic Airlines 426 at 6:23a
return from LAX on Arctic Airlines 593 at 9:27a
Leave SEA on Arctic Airlines 426 at 6:23a
return from LAX on Arctic Airlines 102 at 12:30p
Leave SEA on Arctic Airlines 433 at 9:00a
return from LAX on Arctic Airlines 102 at 12:30p</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="h14">
						<span class="smalltitle">
								<strong>
										<font face="Arial">与文档模型的比较</font>
								</strong>
						</span>
				</a>
		</p>
		<p>这里我不准备全面讨论使用 XML 文档模型的等价代码，那太复杂了，足以单独成章。解决这个问题最简单的方式，可能是首先解析 <code>carrier</code> 元素，创建每个标识符代码到相应对象之间的映射链接。然后使用和 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code9"><font color="#996699">清单 9</font></a>中示例代码类似的逻辑。和使用 bean 的例子相比，每一步都更加复杂，因为代码使用的是 XML 成分而不是真正的数据值。性能可能更糟——只对数据进行少量的操作还不算是问题，但是如果数据处理是应用程序的核心，这就会成为一个主要的焦点。 </p>
		<p>如果在 bean 和 XML 的映射中使用更多的数据类型转换，差别会更大（无论从代码的复杂性还是从性能的角度看）。比方说，假设您使用很多的航班时间，可能希望把文本时间转化成一种更好的国际化表示（如一天内的分钟数，参见 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#code9"><font color="#996699">清单 9</font></a>）。您可以选择为文本和国际化格式定义可以替换的 <code>get</code> 和 <code>set</code> 方法（让映射仅仅使用文本形式），也可以定义一个定制的 <code>org.exolab.castor.mapping.FieldHandler</code> 实现让 Castor 使用这些值。保留时间值的内部形式，可以避免匹配清单 9 中的航班时进行转换，也许还能加快处理速度。 </p>
		<p>除了本文中所述的之外—— <code>FieldHandler</code> 只是一个例子，Castor 还有许多迷人的特性。但愿这些例子和讨论使您能够初步领略这个框架的强大功能和灵活性。 我相信，您将和我一样发现 Castor 非常有用也非常有趣。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="h15">
						<span class="atitle">结束语</span>
				</a>
		</p>
		<p>对于使用 XML 交换数据的应用程序，数据绑定是文档模型很好的替代品。它简化了编程，因为您不必再按照 XML 的方式思考。相反，您可以直接使用代表应用程序所用数据含义的对象。与文档模型相比，它还潜在地提供了更好的内存和处理器使用效率。</p>
		<p>本文中，我使用 Castor 框架展示了一些越来越复杂的数据绑定的例子。所有这些例子都使用所谓的 <i>直接</i>数据绑定：开发人员根据数据定义类，然后把数据映射到 XML 文档结构。下一篇文章中，我将探讨另一种方法： <i>模式</i>数据绑定，利用模式（如 DTD、XML 模式或者其他的类型）生成和那个模式对应的代码。 </p>
		<p>Castor 同时支持模式方法和本文中介绍的直接绑定，您将在以后看到更多的 Castor 应用。我还关注着 JSR-031 Java 数据绑定标准的进展，并对这些方法的性能进行比较。更多了解 Java 中的 XML 数据绑定这个领域，请速来访问离您最近的 IBM <i>developerWorks</i>。 </p>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/library/x-bindcastor/index.html?S_TACT=105AGX52&amp;S_CMP=cn-a-x"><font color="#5c81a7">英文原文</font></a>. <br /><br /></li>
				<li>请在 <a href="javascript:void forumWindow()"><font color="#5c81a7">讨论论坛</font></a>参与本文的讨论。（您也可以单击本文顶部或底部的 <b>讨论</b>来访问论坛。） <br /><br /><br /><br /></li>
				<li>下载包含本文所用示例程序和库的 <a href="http://www.ibm.com/developerworks/cn/xml/x-bindcastor/code.jar"><font color="#5c81a7">jar 压缩文件</font></a>。 <br /><br /><br /><br /></li>
				<li>了解 Castor 的最新进展，请访问该项目的 <a href="http://www.castor.org/"><font color="#996699">主页</font></a>。 <br /><br /><br /><br /></li>
				<li>回顾作者以前的 <i>developerWorks</i>文章，包括 Java XML 文档模型的 <a href="http://www.ibm.com/developerworks/cn/xml/x-injava/index.html"><font color="#5c81a7">性能</font></a>（2001 年 9 月）和 <a href="http://www.ibm.com/developerworks/cn/xml/x-injava2/index.html"><font color="#5c81a7">用法</font></a>（2002 年 2 月）的比较。 <br /><br /><br /><br /></li>
				<li>其他作者对使用 Castor XML 数据绑定的看法，阅读 Scott L. Bain 的论文 “ <a href="http://www.netobjectives.com/xml/download/castor.pdf"><font color="#5c81a7">XML Data Binding with Castor</font></a>”以及 Dion Almaer 在 <i>OnJava.com</i>上的文章 “ <a href="http://www.onjava.com/pub/a/onjava/2001/10/24/xmldatabind.html"><font color="#5c81a7">XML Data Binding with Castor</font></a>”。 <br /><br /><br /><br /></li>
				<li>Sam Brodkin 的 <i>JavaWorld</i>文章，“ <a href="http://www.javaworld.com/javaworld/jw-12-2001/jw-1228-jaxb.html"><font color="#5c81a7">Use XML data binding to do your laundry</font></a>”，比较了JAXB 和 Castor XML 数据绑定。 <br /><br /><br /><br /></li>
				<li>Jacek Kruszelnicki 的 <i>JavaWorld</i>文章，“ <a href="http://www.javaworld.com/javaworld/jw-04-2002/jw-0412-jdo.html?"><font color="#5c81a7">Persist data with Java Data Objects, Part 2</font></a>”，比较了 Castor 和 Sun JDO 的数据绑定和数据存储。 <br /><br /><br /><br /></li>
				<li>最后，看一看 <a href="http://www.ibm.com/developerworks/cgi-bin/click.cgi?S_TACT=105AGX52&amp;S_CMP=cn-a-x&amp;url=http://www-4.ibm.com/software/ad/studioappdev/&amp;origin=x"><font color="#5c81a7">IBM WebSphere Studio Application Developer</font></a>，这是一个创建、测试和部署 J2EE 应用程序简单易用的集成开发环境，包括从 DTD 和模式生成 XML 文档。 <br /><br /><br /><br /></li>
				<li>
						<b>其他链接</b>
						<ul>
								<li>阅读并下载 <a href="http://java.sun.com/xml/jaxb/index.html"><font color="#5c81a7">Java Architecture for XML Binding</font></a>(JAXB) 。 
</li>
								<li>进一步了解 <a href="http://jcp.org/jsr/detail/031.jsp"><font color="#5c81a7">JSR 31 - XML Data Binding Specification</font></a>。 </li>
						</ul>
						<br />
				</li>
		</ul>
		<br />
		<br />
		<p>
				<a name="author">
						<span class="atitle">关于作者</span>
				</a>
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td colspan="3">
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
								</td>
						</tr>
						<tr valign="top" align="left">
								<td>
										<p>
										</p>
								</td>
								<td>
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" />
								</td>
								<td width="100%">
										<p>Dennis Sosnoski 是西雅图地区 Java 咨询公司 <a href="http://www.sosnoski.com/"><font color="#5c81a7">Sosnoski Software Solutions, Inc.</font></a>的创始人和首席顾问，他是 J2EE、XML 和 Web 服务支持方面的专家。他已经有 30 多年专业软件开发经验，最近几年他集中研究服务器端的 Java 技术。Dennis 经常在全国性的会议上就 XML 和 Java 技术发表演讲，您可以通过 <a href="mailto:dms@sosnoski.com?cc=dms@sosnoski.com"><font color="#5c81a7">dms@sosnoski.com</font></a>与 Dennis 联系。</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/zhuyan/aggbug/105944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhuyan/" target="_blank">朱岩</a> 2007-03-23 17:52 <a href="http://www.blogjava.net/zhuyan/articles/105944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Castor是ExoLab Group下面的一个开放源代码的项目</title><link>http://www.blogjava.net/zhuyan/articles/105757.html</link><dc:creator>朱岩</dc:creator><author>朱岩</author><pubDate>Fri, 23 Mar 2007 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/zhuyan/articles/105757.html</guid><wfw:comment>http://www.blogjava.net/zhuyan/comments/105757.html</wfw:comment><comments>http://www.blogjava.net/zhuyan/articles/105757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhuyan/comments/commentRss/105757.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhuyan/services/trackbacks/105757.html</trackback:ping><description><![CDATA[
		<br />
		<center>
				<h4>castor概述</h4>
		</center>
		<br />(<font color="#008000"><em>by </em>huihoo.com</font> reimon) <br /><br />Castor是ExoLab Group下面的一个开放源代码的项目，它主要实现的是O/R映射功能。它主要API和数据接口为：JDO-like, SQL, OQL, JDBC, LDAP, XML, DSML。它支持分布式目录事务处理和时间；提供处理XML、Directory、XADirectory的类库，提供从XML到JAVA类的转换机制。 <br /><br />上面这段是网上的一段评论，大概介绍了Castor的一些特性，我们需要注意的是，Castor所提供的是Castor JDO，而不是SUN所提供的JDO规范（JSR000012），所以在上面的评论中使用了JDO-like这样的评语，在后面我们会进一步讨论这个问题的。 <br /><br />呵呵，不过在我看来，Castor对我们的意义，最重要的就是其XML映射机制和其独创的Castor JDO的机制了。下面我会分别就这两个问题加以介绍： <br /><br /><b>一、Castor XML</b><br /><br />我们可以认为这是一个独立的Framework，专门负责与XML打交道。在了解众多的类和API之前，我们有必要了解其整体的构建思想。在OOP中，我们都知道，对象是类的实体化，我们也知道，在OP中所要完成的工作是将对象持久保存下来，那么相对的，我们同样可以用类似的方法将类的定义和信息也保存下来，这是否可以称为CP呢？呵呵，不管叫什么名字，在Castor中的XML处理中，就是根据这样的思想完成了两个独立的功能块，一块负责类到XML的保存和加载，另一块负责对象到XML的保存和加载。具体的构造我们可以参看下图： <br /><img src="mhtml:file://D:\My Documents\Huihoo Power_ - castor概述.mht!http://docs.huihoo.com/development/oo/i/castor1.gif" /><br /><br />如上图所描述的，marshaller和unmarshaller负责对象和XML文件间的转换。这种转换过程主要在服务器端完成。在运行中，客户端的请求发送到服务器端后，对内存中的对象进行相应操作，然后将处理完毕的对象marshall成为XML文件，或者进一步将XML文件格式化为HTML文件发送到客户端。如果以XML文件格式发送到客户端，那么在客户端实行unmarshall操作将XML文件还原为内存中的对象，这样就完成了交互过程。 <br /><img src="mhtml:file://D:\My Documents\Huihoo Power_ - castor概述.mht!http://docs.huihoo.com/development/oo/i/castor2.gif" /><br /><br />至于source generator则和TOPLINK中实现的相类似，不过它没有提供可视化的XML Schema的工具而已。我们编写好描述类结构的XML文件，然后运行Castor提供的source generator就可以自动生成JAVA代码了。有趣的是，它自动生成的代码和BEAN的风格很类似，很容易看懂。 <br /><br />对于XML而言，只要把握了这样的整体，其他的诸如代码生成中的两种模式、映射规范、数据结构问题等细节问题就很简单了，在文档中附有很实用的例子和解释，这里就不再多说了。 <br /><br /><b>二、Castor JDO</b><br /><br />要了解JDO首先要认识两个基本的问题： <br /><br />1、和SUN JDO的关系 <br /><br />Castor JDO和SUN JDO并不相同，Castor JDO是独立于SUN JDO发展起来的，但是它们所完成的工作非常相似。虽然也可以将Castor JDO重新定制成SUN JDO那个样子，但是由于两者在锁定策略上存在的根本差异，这样做并不划算。在内部，Castor JDO为所有事务中的每个活动的持久性对象只维护一份锁定（和缓存）的备份。而在SUN中则对每个事务中的每个持久性对象各维护一个备份，并且SUN JDO还需要字节码编辑器，而CastorJDO并不需要。Castor还提供了其他的一些特性，比如说key generators，long transaction support 以及 OQL query，这些都在SUN的JSR中是看不到的。所以我们在前面对Castor的评价是JDO-LIKE的。 <br /><br />2、和EJB的关系 <br /><br />Castor和EJB很难说谁更好一些。 <br /><br />一个实体Bean可以管理它自身的持久化。它要么调用BMP（Bean Managed Persistence）来自己管理持久化，要么就依靠它的容器的CMP(Container Managed Persistence)来做到持久化。 <br /><br />对于BMP来说，一个实体BEAN可以使用Castor JDO作为它的持久化机制，也可以使用其他的机制，比如说直接调用JDBC。 <br /><br />对于CMP来说，一个EJB Container可以将它们的CMP基于Castor JDO来实现，那么Castor JDO将被用来将实体BEAN持久化。如果开发者需要EJB的life-cycle管理, , "write once deploy anywhere" 和其他分布式应用程序的优点，那么建议你直接使用EJB。否则，使用Castor将会更简单，而且还开放源代码，开销更小，并提供更多的设计自由性，以及所提供的集成的XML支持。我们应当根据实际情况来选择所使用的机制。 <br /><br />具体的使用我就不知道怎么说了，呵呵，下面把它的一个概括性介绍的文档给翻译了下来，Castor JDO的一些基本的使用特性里面基本上都介绍或者提及了，比如说JDO的两种使用环境的区别、OQL query、生存期问题、基本语义、与XML联用等，如果需要更具体的情况请自行查询Castor的文档。 <br /><br />&lt;翻译来自castor的联机文档－－Castor JDO概况&gt; <br /><br />打开一个JDO数据库 <br /><br />CatorJDO支持两种类型的环境，客户端应用程序和J2EE服务器。客户端应用程序负责设置数据库连接和管理事务处理。J2EE应用程序使用JNDI来获取预先配置好的数据库连接，并且使用UserTransaction或者CMT(container managed transaction)来管理事务。如果你在这两种环境中用过JDBC，那么你对它们之间的异同会很了解。 <br /><br />客户端应用程序 <br /><br />客户端应用程序负责设置数据库连接和管理事务处理。数据库的设置是通过一个与映射文件相连接的独立的XML文件来实现的。在例子中就是database.xml,但是其实我们可以使用任何的名字。 <br /><br />org.exolab.castor.jdo.JDO定义了数据库的名字和属性，并被用来打开一个数据库连接。通过使用setConfiguration命令来指定配置文件URL，我们可以装载数据库的配置。使用同一个配置来创建多个JDO对象只会装载配置文件一次。 org.exolab.castor.jdo.Database对象实现了到数据库的开放连接。在定义里，database对象不是thread safe因而不应该用于并发进程中。当开启多个Database对象是会有一点开销，并且JDBC连接is acquired only per open transaction。下面的代码片显示了在典型的客户端应用程序中的打开一个数据库，运行一个事务，然后关闭数据库的过程。 <br /><br />JDO jdo; <br />Database db; <br /><br />// 定义JDO对象 <br />jdo = new JDO(); <br />jdo.setDatabaseName( "mydb" ); <br />jdo.setConfiguration( "database.xml" ); <br />jdo.setClassLoader( getClass().getClassLoader() ); <br /><br />// 获取一个新的数据库 <br /><br />db = jdo.getDatabase(); <br /><br />// 开始事务处理 <br />db.begin(); <br /><br />// 事务过程 <br />. . . <br /><br />// 提交事务，关闭数据库 <br />db.commit(); <br />db.close(); <br /><br />J2EE 程序( 不太懂，所以没译，大概说的是在J2EE中由于使用持久化方式的不通而产生的编码不同的问题，可以参考一下我们前面对EJB持久化问题的探讨) <br /><br />Note: We are now working on supporting Castor inside a J2EE container. Stay tuned for more information. J2EE applications depend on the J2EE container (Servlet, EJB, etc) to configure the database connection and use JNDI to look it up. This model allows the application deployer to configure the database properties from a central place, and gives the J2EE container the ability to manage distributed transactions across multiple data sources. Instead of constructing a org.exolab.castor.jdo.JDO the application uses the JNDI namespace to look it up. We recommend enlisting the JDO object under the java:comp/env/jdo namespace, compatible with the convention for listing JDBC resources. <br /><br />下面的代码片使用JNDI来查找一个数据库，并且使用UserTransaction来进行事务管理： <br /><br />InitialContext ctx; <br />UserTransaction ut; <br />Database db; <br /><br />// 在JNDI中查找数据库 <br />ctx = new InitialContext(); <br />db = (Database) ctx.lookup( "java:comp/env/jdo/mydb" ); <br /><br />// 开始事务处理 <br />ut = (UserTransaction) ctx.lookup( "java:comp/UserTransaction" ); <br />ut.begin(); <br /><br />// 事务过程 <br />. . . <br /><br />// 提交事务，关闭数据库 <br />ut.commit(); <br />db.close(); <br /><br />When the transaction is managed by the container, a common case with EJB beans and in particular entity beans, there is no need to being/commit the transaction explicitly. Instead the application server takes care of enlisting the database in the ongoing transaction and commiting/rollingback at the proper time. <br /><br />The following code snippet relies on the container to manage the transaction: <br /><br />InitialContext ctx; <br />UserTransaction ut; <br />Database db; <br /><br />// Lookup databse in JNDI <br />ctx = new InitialContext(); <br />db = (Database) ctx.lookup( "java:comp/env/jdo/mydb" ); <br /><br />// Do something <br />. . . <br /><br />// Close the database <br />db.close(); <br /><br />总结：开启一个数据库在客户端和在服务器端是有区别的，主要体现在事务处理的过程、配置问题等上面，需要注意。 <br /><br />使用JDO数据库 <br />临时对象和持久对象 <br />所有的JDO操作都发生在事务中。事务提交时，JDO将数据从数据库中加载到内存中的对象中，让应用程序对对象进行操作，然后再将对象的新状态存储到数据库中。所有的对象可以是两种状态：临时的或者持久的。 <br />临时的：指当事务提交时状态不会被保存的对象。对对象的修改不会表现在数据库中。 <br />持久的：指当事务提交时状态将被保存的对象。对对象的修改将反映在数据库中。 <br />在下面情况下对象为持久的： 1、一个查询的结果， <br />2、使用create(java.lang.Object)或者update(java.lang.Object)将它加入到数据库中。 <br />所有不是持久性的对象就是临时性对象，当事务提交或者回滚时，所有的持久性对象变成临时对象。 <br />在客户端程序中，使用begin()，commit()和rollback()来管理事务。在J2EE程序中，JDO依靠container来含蓄或明确（基于bean的transaction属性值）的使用javax.transaction.UserTransaction接口来管理事务。 <br />如果一个持久对象在事务中被改变了，在提交时修改会存入数据库。如果事务回滚，数据库不会被改变。如果要在两个不同的事务中使用同一个对象，你必须重新查询。 <br />对象的临时和持久是从事务所属的数据库的角度来看的。一般来说持久对象只是对于一个数据库而言，如果在另外一个数据库中调用isPersistent(java.lang.Object)将返回false。当然也可以让一个持久对象对应于两个数据库，比如说在一个数据库中运行查询，而在另一个数据库中创建它。 <br />OQLQuery <br />OQL查询被用来从数据库中查询和寻找对象。OQL查询和SQL查询类似，但是使用对象名称而不是SQL名称，并且不需要join子句。比如说，如果类型为TestObject的对象被加载了，OQL查询将使用“FROM TestObject”，而不管到底表名为什么。如果加载关联的对象需要join，Castor将自动实现连接。 <br />下面的代码片使用OQL查询来加载指定组中所有的对象。注意产品和组是关联的对象，JDBC查询使用了连接： <br /><br />OQLQuery oql; <brt>QueryResults results; <br /><br />// Construct a new query and bind its parameters <br />oql = db.getOQLQuery( "SELECT p FROM Product p WHERE Group=$" ); <br />oql.bind( groupId ); <br /><br />// Retrieve results and print each one <br />results = oql.execute(); <br />while ( results.hasMore() ) { <br />System.out.println( results.next() ); <br />} <br /><br />下面的代码片使用前面的查询来获得产品，将它们的价格减少25%，并且将它们存会数据库（在这里使用了客户端程序事务）： <br />while ( results.hasMore() ) { <br />Product prod; <br />prod = (Product) results.next(); <br />prod.markDown( 0.25 ); <br />prod.setOnSale( true ); <br />} <br /><br />// Explicitly commit transaction <br />db.commit(); <br />db.close(); <br /><br />如上面所描述的，查询分三个步骤实现：一、使用OQL语法从数据库中创建一个query对象；二、如果有参数，就将参数绑定到查询中。参数绑定的顺序和它们在OQL语法中出现的顺序保持一致；三、执行查询并获得一系列为org.exolab.castor.jdo.QueryResults的对象。查询创建一次后可以多次使用，不过每次都得重新绑定参数。查询再次执行后，上一次的结果集可以继续使用。参考下面的代码来调用存储过程： <br />oql = db.getOQLQuery( "CALL sp_something($) AS myapp.Product" ); 在这里sp_something是一个返回一个或多个结果集的存储过程，字段顺序和前面相同（对于没有关联的对象，顺序为：标识符，接下来是所有其他的字段，顺序和mapping.xml中定义的顺序一致）。 <br />Create/remove/update <br />create(java.lang.Object)方法在数据库中创建一个新的对象，或者在JDO terminology中使得一个临时对象持久化。如果事务被提交的话，这个使用create方法创建的对象将保持在数据库中，否则将被删除。如果使用数据库中已经存在的标识来创建对象，将会产生一个异常。 下面的代码片为先前查询出来的一个组创建了一个新的产品： <br /><br />Product prod; <br />// Create the Product object <br />prod = new Product(); <br />prod.setSku( 5678 ); <br />prod.setName( "Plastic Chair" ); <br />prod.setPrice( 55.0 ); <br />prod.setGroup( furnitures ); <br /><br />// Make is persistent <br />db.create( prod ); <br /><br />remove(java.lang.Object)方法产生相反的效果，它将删除一个持久性对象。一旦删除，任何事务都无法使用该对象。如果事务提交，这个对象将从数据库中删除，否则对象将仍然存在于数据库中。如果试图删除一个非持久性对象，将产生异常。 <br /><br />使用 JDO 和 XML <br /><br />CastorJDO和CastorXML结合起来，可以通过使用XML作为输入和输出来实现事务性数据库操作。下面的程序片使用持久性和临时性对象的结合来描述一个财务操作。 <br /><br />这个例子获取了两个account对象并且从其中一个转移了一笔金额到另外一个账户。转移被描述为使用一个临时对象（比如说无数据库中的记录），这个对象接下来被用于生成一个XML文档来描述这次转移过程。另外还有一个附加的过程（这里没有表现出来），是使用XSLT来将XML文档转换为一个HTML页面。 <br /><br />Transfer tran; <br />Account from; <br />Account to; <br />OQLQuery oql; <br />tran = new Transfer(); <br /><br />// Construct a query and load the two accounts <br />oql = db.getOQLQuery( "SELECT a FROM Account a WHERE Id=$" ); <br />oql.bind( fromId ); <br />from = oql.execute().nextElement(); <br />oql.bind( toId ); <br />to = oql.execute().nextElement(); <br /><br />// Move money from one account to the other <br />if ( from.getBalance() &gt;= amount ) { <br />from.decBalance( amount ); <br />to.incBalance( amount ); <br />trans.setStatus( Transfer.COMPLETE ); <br />trans.setAccount( from ); <br />trans.setAmount( amount ); <br />} else { <br /><br />// Report an overdraft <br />trans.setStatus( Transfer.OVERDRAFT ); <br />} <br /><br />// Produce an XML describing the transfer <br />Marshaller.marshal( trans, outputStream ); <br />The XML produced by the above code might look like: <br /><br /><brt><br /><report><br /><status>Completed</status><br /><account id="1234-5678-90" balance="50" /><br /><transfer amount="49.99" /><br /></report><br /><br />总结：在使用数据库的过程中，我们需要区分好临时对象和持久对象，并掌握灵活运用它们的方法，另外，Castor所支持的OQL的用法也值得研究，我们可以参考Castor所提供的详细文档进一步了解。</brt></brt><img src ="http://www.blogjava.net/zhuyan/aggbug/105757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhuyan/" target="_blank">朱岩</a> 2007-03-23 10:43 <a href="http://www.blogjava.net/zhuyan/articles/105757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>