﻿<?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-Jelver'Sky-文章分类-PatterDesign/UML/Rose/ERwin</title><link>http://www.blogjava.net/jelver/category/7679.html</link><description>“一直很多人说我是天才，但我却相信这个世界没有天才。如果没有卓越的努力和娴熟的球性，你永远不会踢出精彩的足球。我从3岁开始踢球，7岁进入格雷米奥少年队开始接受系统训练，至今为止已经踢了20年的球。如果你认为这纯粹是天才，那为什么我14岁时没有现在这种天才呢？我从来不会低估努力的重要性，而这正是我对自己的要求。”
---------罗纳尔迪尼奥(Ronaldinho)</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:27:24 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:27:24 GMT</pubDate><ttl>60</ttl><item><title>类与类关系的UML图与代码表现 (转)</title><link>http://www.blogjava.net/jelver/articles/87448.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Wed, 13 Dec 2006 04:37:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/87448.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/87448.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/87448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/87448.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/87448.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Arial">原文：<a href="http://www.javaeye.com/topic/37302?page=1">http://www.javaeye.com/topic/37302?page=1</a><br />类与类之间的关系对于理解面向对象具有很重要的作用，以前在面试的时候也经常被问到这个问题，在这里我就介绍一下。<br />类与类之间存在以下关系:<br /><strong><font color="#3366ff">(1)泛化(Generalization)<br />(2)关联(Association)<br />(3)依赖(Dependency)<br />(4)聚合(Aggregation)</font></strong></font>
		</p>
		<p>
				<font face="Arial">
						<strong>UML图与应用代码例子:</strong>
						<br />
						<strong>
								<font color="#ff9900" size="4">
										<font color="#3366ff">1.泛化(Generalization)</font>
										<br />
								</font>
								<font color="#339966" size="3">[泛化]</font>
								<br />
						</strong>表示类与类之间的继承关系，接口与接口之间的继承关系，或类对接口的实现关系。一般化的关系是从子类指向父类的，与继承或实现的方法相反。<br /><font color="#339966" size="3"><strong>[具体表现]<br /></strong></font><font color="#ff0000">父类</font> 父类实例＝new <font color="#ff0000">子类</font>()<br /><strong><font color="#339966" size="3">[UML图](图1.1)<br /></font><img alt="" src="http://seagar.javaeye.com/upload/picture/pic/1320/10bfdb9d-ed2d-4226-bab2-f814d2e10a82.jpg" /><br /></strong><font face="Arial"><font color="#339966"><strong>图1.1</strong></font><strong>Animal类与Tiger类,Dog类的泛化关系<br /></strong></font><br /><strong><font color="#339966" size="3">[代码表现]</font><br /><br /></strong></font>
		</p>
		<div class="dp-highlighter">
				<div class="bar">
						<strong>
						</strong>
				</div>
				<ol class="dp-j">
						<li class="alt">
								<span>
										<span class="keyword">class</span>
										<span>
												<strong> Animal{}   </strong>
										</span>
								</span>
								<strong>
								</strong>
						</li>
						<li class="">
								<span>
								</span>
								<span class="keyword">class</span>
								<strong>
										<span> Tiger </span>
										<span class="keyword">extends</span>
										<span> Animal{}   </span>
								</strong>
						</li>
						<li class="alt">
								<span>
								</span>
								<span class="keyword">public</span>
								<strong>
										<span> </span>
										<span class="keyword">class</span>
										<span> Test   </span>
								</strong>
						</li>
						<li class="">
								<strong>
										<span>{   </span>
								</strong>
						</li>
						<li class="alt">
								<strong>
										<span>    </span>
										<span class="keyword">public</span>
										<span> </span>
										<span class="keyword">void</span>
										<span> test()   </span>
								</strong>
						</li>
						<li class="">
								<strong>
										<span>    {   </span>
								</strong>
						</li>
						<li class="alt">
								<strong>
										<span>        Animal a=</span>
										<span class="keyword">new</span>
										<span> Tiger();   </span>
								</strong>
						</li>
						<li class="">
								<strong>
										<span>    }   </span>
								</strong>
						</li>
						<li class="alt">
								<strong>
										<span>}  </span>
								</strong>
						</li>
				</ol>
		</div>
		<br />
		<font face="Arial">
				<strong>
						<font color="#3366ff" size="4">2.依赖(Dependency)</font>
						<br />
				</strong>
				<font color="#339966" size="3">
						<strong>[依赖]<br /></strong>
				</font>对于两个相对独立的对象，当一个对象负责构造另一个对象的实例，或者依赖另一个对象的服务时，这两个对象之间主要体现为依赖关系。<br /><font color="#339966" size="3"><strong>[具体表现]<br /></strong></font>依赖关系表现在<font color="#ff0000">局部变量</font>，<font color="#ff0000">方法的参数</font>，以及对<font color="#ff0000">静态方法的调用</font><br /><font color="#339966" size="3"><strong>[现实例子]<br /></strong></font>比如说你要去拧螺丝，你是不是要借助(也就是依赖)螺丝刀(Screwdriver)来帮助你完成拧螺丝(screw)的工作<br /><font color="#339966" size="3"><strong>[UML表现](图1.2)</strong></font><br /><p align="left"><strong><img alt="" src="http://seagar.javaeye.com/upload/picture/pic/1319/ec7bca6c-c01a-4772-a91b-3a695773ddfb.jpg" /></strong></p><p align="left"><br /><font face="Arial"><strong><font color="#339966">图1.2 </font>Person类与Screwdriver类的依赖关系</strong><br /><font face="Arial"><font color="#339966" size="3"><strong><br />[代码表现] </strong></font></font></font></p><div class="dp-highlighter"><div class="bar"><strong></strong></div><ol class="dp-j"><li class="alt"><span><span class="keyword">public</span><strong><span> </span><span class="keyword">class</span><span> Person{   </span></strong></span><strong></strong></li><li class=""><strong><span>    </span><span class="comment">/** 拧螺丝 */</span><span>  </span></strong></li><li class="alt"><strong><span>    </span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> screw(Screwdriver screwdriver){   </span></strong></li><li class=""><strong><span>        screwdriver.screw();   </span></strong></li><li class="alt"><strong><span>    }   </span></strong></li><li class=""><strong><span>}  </span></strong></li></ol></div><br /><font face="Arial"><strong><font color="#3366ff" size="4">3.关联(Association)</font><br /></strong><font color="#339966" size="3"><strong>[关联]<br /></strong></font>对于两个相对独立的对象，当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时，这两个对象之间为关联关系。<br /><font color="#339966" size="3"><strong>[具体表现]<br /></strong></font>关联关系是使用<font color="#ff0000">实例变量</font>来实现<br /><font color="#339966" size="3"><strong>[现实例子]<br /></strong></font>比如客户和订单，每个订单对应特定的客户，每个客户对应一些特定的订单；再例如公司和员工，每个公司对应一些特定的员工，每个员工对应一特定的公司<br /><strong><font color="#339966" size="3">[UML图] (图1.3)<br /></font><img alt="" src="http://seagar.javaeye.com/upload/picture/pic/1318/d4b10677-364d-4c34-beb7-416f8e835d8c.jpg" /><br /><font face="Arial"><strong><font color="#339966">图1.3 </font></strong>公司和员工的关联关系</font></strong></font><br /><font face="Arial"><strong><br /><font color="#339966" size="3">[代码表现]</font></strong><div class="dp-highlighter"><div class="bar"><strong></strong></div><ol class="dp-j"><li class="alt"><span><span class="keyword">public</span><strong><span> </span><span class="keyword">class</span><span> Company{   </span></strong></span><strong></strong></li><li class=""><strong><span>    </span><span class="keyword">private</span><span> Employee employee;   </span></strong></li><li class="alt"><strong><span>    </span><span class="keyword">public</span><span> Employee getEmployee(){   </span></strong></li><li class=""><strong><span>        </span><span class="keyword">return</span><span> employee;   </span></strong></li><li class="alt"><strong><span>    }   </span></strong></li><li class=""><strong><span>    </span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setEmployee(Employee employee){   </span></strong></li><li class="alt"><strong><span>        </span><span class="keyword">this</span><span>.employee=employee;   </span></strong></li><li class=""><strong><span>    }   </span></strong></li><li class="alt"><strong><span>    </span><span class="comment">//公司运作 </span><span>  </span></strong></li><li class=""><strong><span>    </span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> run(){   </span></strong></li><li class="alt"><strong><span>        employee.startWorking();   </span></strong></li><li class=""><strong><span>    }   </span></strong></li><li class="alt"><strong><span>}  </span></strong></li></ol></div></font></font>
		<font face="Arial">
				<strong>
						<font color="#3366ff" size="4">(4)聚合（Aggregation）</font>
						<br />
						<font color="#339966" size="3">[聚合]<br /></font>
				</strong>当对象A被加入到对象B中，成为对象B的组成部分时，对象B和对象A之间为聚集关系。聚合是关联关系的一种，是较强的关联关系，强调的是<font color="#ff0000">整体</font>与<font color="#ff0000">部分</font>之间的关系。<br /><font color="#339966" size="3"><strong>[具体表现]<br /></strong></font>与关联关系一样，聚合关系也是通过<font color="#ff0000">实例变量</font>来实现这样关系的。关联关系和聚合关系来语法上是没办法区分的，从<font color="#ff0000">语义</font>上才能<font color="#ff0000">更好的区分</font>两者的区别。<br /><font color="#339966" size="3"><strong>[关联与聚合的区别]</strong></font><br />(1)关联关系所涉及的两个对象是处在同一个层次上的。比如人和自行车就是一种关联关系，而不是聚合关系，因为人不是由自行车组成的。<br />聚合关系涉及的两个对象处于不平等的层次上，一个代表整体，一个代表部分。比如电脑和它的显示器、键盘、主板以及内存就是聚集关系，因为主板是电脑的组成部分。<br />(2)对于具有聚集关系（尤其是强聚集关系）的两个对象，整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在，它的生命周期依赖于整体类的对象的生命周期，当整体消失，部分也就随之消失。比如张三的电脑被偷了，那么电脑的所有组件也不存在了，除非张三事先把一些电脑的组件（比如硬盘和内存）拆了下来。<br /><font color="#339966" size="3"><strong>[UML图](图1.4)</strong></font><br /><strong><img alt="" src="http://seagar.javaeye.com/upload/picture/pic/1326/7032798b-36ca-4b89-a462-97ba056cbe48.jpg" /><br /><font face="Arial"><strong><font color="#339966">图1.3 </font><font color="#000000">电脑和组件的聚合关系</font></strong></font><br /><br /><font face="Arial"><font color="#339966" size="3"><strong>[代码表现]</strong></font></font></strong><div class="dp-highlighter"><div class="bar"><strong></strong></div><ol class="dp-j"><li class="alt"><span><span class="keyword">public</span><strong><span> </span><span class="keyword">class</span><span> Computer{   </span></strong></span><strong></strong></li><li class=""><strong><span>    </span><span class="keyword">private</span><span> CPU cpu;   </span></strong></li><li class="alt"><strong><span>    </span><span class="keyword">public</span><span> CPU getCPU(){   </span></strong></li><li class=""><strong><span>        </span><span class="keyword">return</span><span> cpu;   </span></strong></li><li class="alt"><strong><span>    }   </span></strong></li><li class=""><strong><span>    </span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setCPU(CPU cpu){   </span></strong></li><li class="alt"><strong><span>        </span><span class="keyword">this</span><span>.cpu=cpu;   </span></strong></li><li class=""><strong><span>    }   </span></strong></li><li class="alt"><strong><span>    </span><span class="comment">//开启电脑 </span><span>  </span></strong></li><li class=""><strong><span>    </span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> start(){   </span></strong></li><li class="alt"><strong><span>        </span><span class="comment">//cpu运作 </span><span>  </span></strong></li><li class=""><strong><span>        cpu.run();   </span></strong></li><li class="alt"><strong><span>    }   </span></strong></li><li class=""><strong><span>}  </span></strong></li></ol></div><br /><br /><font face="Arial" color="#99cc00"><strong>[参考资料]<br />1.《Java与模式》(阎宏 编著) 第2章 统一建模语言UML简介</strong></font></font>
<img src ="http://www.blogjava.net/jelver/aggbug/87448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-12-13 12:37 <a href="http://www.blogjava.net/jelver/articles/87448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>总结一下最近关于domain object以及相关的讨论 </title><link>http://www.blogjava.net/jelver/articles/41009.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 14 Apr 2006 00:50:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/41009.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/41009.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/41009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/41009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/41009.html</trackback:ping><description><![CDATA[
		<span class="postbody">
				<a href="http://forum.javaeye.com/viewtopic.php?t=11712">http://forum.javaeye.com/viewtopic.php?t=11712</a>
				<br />
				<br />在最近的围绕domain object的讨论中浮现出来了三种模型，(还有一些其他的旁枝，不一一分析了)，经过一番讨论，各种问题逐渐清晰起来，在这里我试图做一个总结，便于大家了解和掌握。 <br /><br />第一种模型：只有getter/setter方法的纯数据类，所有的业务逻辑完全由business object来完成(又称TransactionScript)，这种模型下的domain object被Martin Fowler称之为“贫血的domain object”。下面用举一个具体的代码来说明，代码来自Hibernate的caveatemptor，但经过我的改写： <br /><br />一个实体类叫做Item，指的是一个拍卖项目 <br />一个DAO接口类叫做ItemDao <br />一个DAO接口实现类叫做ItemDaoHibernateImpl <br />一个业务逻辑类叫做ItemManager(或者叫做ItemService) <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<div style="FONT-FAMILY: 'Courier New', Courier, monospace">
												<br />
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span>
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> Item <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">implements</span><span style="COLOR: #aaaadd" ?="">Serializable</span><span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Long</span> id = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">null</span>; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">int</span> version; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">String</span> name; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> User seller; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">String</span> description; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> MonetaryAmount initialPrice; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> MonetaryAmount reservePrice; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Date</span> startDate; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Date</span> endDate; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Set</span> categorizedItems = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">HashSet</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Collection</span> bids = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">ArrayList</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> Bid successfulBid; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> ItemState state; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> User approvedBy; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Date</span> approvalDatetime; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="COLOR: #aaaadd" ?="">Date</span> created = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">Date</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #6666ff">//  getter/setter方法省略不写，避免篇幅太长</span><br /><span style="COLOR: #000000">}</span></div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<div style="FONT-FAMILY: 'Courier New', Courier, monospace">
												<br />
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span>
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">interface</span> ItemDao <span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Item getItemById<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Long</span> id<span style="COLOR: #000000">)</span>; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="COLOR: #aaaadd" ?="">Collection</span> findAll<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> updateItem<span style="COLOR: #000000">(</span>Item item<span style="COLOR: #000000">)</span>; <br /><span style="COLOR: #000000">}</span></div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />ItemDao定义持久化操作的接口，用于隔离持久化代码。 <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<div style="FONT-FAMILY: 'Courier New', Courier, monospace">
												<br />
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span>
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> ItemDaoHibernateImpl <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">implements</span> ItemDao <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">extends</span> HibernateDaoSupport <span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Item getItemById<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Long</span> id<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span><span style="COLOR: #000000">(</span>Item<span style="COLOR: #000000">)</span> getHibernateTemplate<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">load</span><span style="COLOR: #000000">(</span>Item.<span style="COLOR: #000000">class</span>, id<span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="COLOR: #aaaadd" ?="">Collection</span> findAll<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span><span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">List</span><span style="COLOR: #000000">)</span> getHibernateTemplate<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">find</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"from Item"</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> updateItem<span style="COLOR: #000000">(</span>Item item<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        getHibernateTemplate<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">update</span><span style="COLOR: #000000">(</span>item<span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />ItemDaoHibernateImpl完成具体的持久化工作，请注意，数据库资源的获取和释放是在ItemDaoHibernateImpl里面处理的，每个DAO方法调用之前打开Session，DAO方法调用之后，关闭Session。(Session放在ThreadLocal中，保证一次调用只打开关闭一次) <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>java代码: </b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<div style="FONT-FAMILY: 'Courier New', Courier, monospace">
												<br />
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span>
												<span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> ItemManager <span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> ItemDao itemDao; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> setItemDao<span style="COLOR: #000000">(</span>ItemDao itemDao<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span> this.<span style="COLOR: #000000">itemDao</span> = itemDao;<span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid loadItemById<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Long</span> id<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        itemDao.<span style="COLOR: #000000">loadItemById</span><span style="COLOR: #000000">(</span>id<span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="COLOR: #aaaadd" ?="">Collection</span> listAllItems<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span>  itemDao.<span style="COLOR: #000000">findAll</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid placeBid<span style="COLOR: #000000">(</span>Item item, User bidder, MonetaryAmount bidAmount, <br />                            Bid currentMaxBid, Bid currentMinBid<span style="COLOR: #000000">)</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">throws</span> BusinessException <span style="COLOR: #000000">{</span><br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span>currentMaxBid != <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">null</span> &amp;&amp; currentMaxBid.<span style="COLOR: #000000">getAmount</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">compareTo</span><span style="COLOR: #000000">(</span>bidAmount<span style="COLOR: #000000">)</span> &gt; <span style="COLOR: #000000" ?="">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />            throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Bid too low."</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <br />    <span style="COLOR: #6666ff">// Auction is active</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> !state.<span style="COLOR: #000000">equals</span><span style="COLOR: #000000">(</span>ItemState.<span style="COLOR: #000000">ACTIVE</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />            throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Auction is not active yet."</span><span style="COLOR: #000000">)</span>; <br />    <br />    <span style="COLOR: #6666ff">// Auction still valid</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> item.<span style="COLOR: #000000">getEndDate</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">before</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">Date</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />            throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Can't place new bid, auction already ended."</span><span style="COLOR: #000000">)</span>; <br />    <br />    <span style="COLOR: #6666ff">// Create new Bid</span><br />    Bid newBid = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> Bid<span style="COLOR: #000000">(</span>bidAmount, item, bidder<span style="COLOR: #000000">)</span>; <br />    <br />    <span style="COLOR: #6666ff">// Place bid for this Item</span><br />    item.<span style="COLOR: #000000">getBids</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">add</span><span style="COLOR: #000000">(</span>newBid<span style="COLOR: #000000">)</span>; <br />    itemDao.<span style="COLOR: #000000">update</span><span style="COLOR: #000000">(</span>item<span style="COLOR: #000000">)</span>;     <span style="COLOR: #6666ff">//  调用DAO完成持久化操作</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span> newBid; <br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />事务的管理是在ItemManger这一层完成的，ItemManager实现具体的业务逻辑。除了常见的和CRUD有关的简单逻辑之外，这里还有一个placeBid的逻辑，即项目的竞标。 <br /><br />以上是一个完整的第一种模型的示例代码。在这个示例中，placeBid，loadItemById，findAll等等业务逻辑统统放在ItemManager中实现，而Item只有getter/setter方法<br /><br /><span class="postbody">第二种模型，也就是Martin Fowler指的rich domain object是下面这样子的： <br /><br />一个带有业务逻辑的实体类，即domain object是Item <br />一个DAO接口ItemDao <br />一个DAO实现ItemDaoHibernateImpl <br />一个业务逻辑对象ItemManager <br /><br /></span><table cellspacing="1" cellpadding="3" width="90%" align="center" border="0"><tbody><tr><td><span class="genmed"><b>java代码: </b></span></td></tr><tr><td class="code"><div style="FONT-FAMILY: 'Courier New', Courier, monospace"><br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> Item <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">implements</span><span style="COLOR: #aaaadd" ?="">Serializable</span><span style="COLOR: #000000">{</span><br />    <span style="COLOR: #6666ff">//  所有的属性和getter/setter方法同上，省略</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid placeBid<span style="COLOR: #000000">(</span>User bidder, MonetaryAmount bidAmount, <br />                        Bid currentMaxBid, Bid currentMinBid<span style="COLOR: #000000">)</span><br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">throws</span> BusinessException <span style="COLOR: #000000">{</span><br />    <br />            <span style="COLOR: #6666ff">// Check highest bid (can also be a different Strategy (pattern))</span><br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span>currentMaxBid != <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">null</span> &amp;&amp; currentMaxBid.<span style="COLOR: #000000">getAmount</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">compareTo</span><span style="COLOR: #000000">(</span>bidAmount<span style="COLOR: #000000">)</span> &gt; <span style="COLOR: #000000" ?="">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />                    throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Bid too low."</span><span style="COLOR: #000000">)</span>; <br />            <span style="COLOR: #000000">}</span><br />    <br />            <span style="COLOR: #6666ff">// Auction is active</span><br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> !state.<span style="COLOR: #000000">equals</span><span style="COLOR: #000000">(</span>ItemState.<span style="COLOR: #000000">ACTIVE</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />                    throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Auction is not active yet."</span><span style="COLOR: #000000">)</span>; <br />    <br />            <span style="COLOR: #6666ff">// Auction still valid</span><br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> this.<span style="COLOR: #000000">getEndDate</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">before</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">Date</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />                    throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Can't place new bid, auction already ended."</span><span style="COLOR: #000000">)</span>; <br />    <br />            <span style="COLOR: #6666ff">// Create new Bid</span><br />            Bid newBid = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> Bid<span style="COLOR: #000000">(</span>bidAmount, this, bidder<span style="COLOR: #000000">)</span>; <br />    <br />            <span style="COLOR: #6666ff">// Place bid for this Item</span><br />            this.<span style="COLOR: #000000">getBids</span>.<span style="COLOR: #000000">add</span><span style="COLOR: #000000">(</span>newBid<span style="COLOR: #000000">)</span>;  <span style="COLOR: #6666ff">// 请注意这一句，透明的进行了持久化，但是不能在这里调用ItemDao，Item不能对ItemDao产生依赖！</span><br />    <br />            <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span> newBid; <br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div><br /></td></tr></tbody></table><span class="postbody"><br /><br />竞标这个业务逻辑被放入到Item中来。请注意this.getBids.add(newBid); 如果没有Hibernate或者JDO这种O/R Mapping的支持，我们是无法实现这种透明的持久化行为的。但是请注意，Item里面不能去调用ItemDAO，对ItemDAO产生依赖！ <br /><br />ItemDao和ItemDaoHibernateImpl的代码同上，省略。 <br /><br /></span><table cellspacing="1" cellpadding="3" width="90%" align="center" border="0"><tbody><tr><td><span class="genmed"><b>java代码: </b></span></td></tr><tr><td class="code"><div style="FONT-FAMILY: 'Courier New', Courier, monospace"><br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> ItemManager <span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> ItemDao itemDao; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> setItemDao<span style="COLOR: #000000">(</span>ItemDao itemDao<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span> this.<span style="COLOR: #000000">itemDao</span> = itemDao;<span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid loadItemById<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Long</span> id<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        itemDao.<span style="COLOR: #000000">loadItemById</span><span style="COLOR: #000000">(</span>id<span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="COLOR: #aaaadd" ?="">Collection</span> listAllItems<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span>  itemDao.<span style="COLOR: #000000">findAll</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid placeBid<span style="COLOR: #000000">(</span>Item item, User bidder, MonetaryAmount bidAmount, <br />                            Bid currentMaxBid, Bid currentMinBid<span style="COLOR: #000000">)</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">throws</span> BusinessException <span style="COLOR: #000000">{</span><br />        item.<span style="COLOR: #000000">placeBid</span><span style="COLOR: #000000">(</span>bidder, bidAmount, currentMaxBid, currentMinBid<span style="COLOR: #000000">)</span>; <br />        itemDao.<span style="COLOR: #000000">update</span><span style="COLOR: #000000">(</span>item<span style="COLOR: #000000">)</span>;    <span style="COLOR: #6666ff">// 必须显式的调用DAO，保持持久化</span><br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div><br /></td></tr></tbody></table><span class="postbody"><br /><br />在第二种模型中，placeBid业务逻辑是放在Item中实现的，而loadItemById和findAll业务逻辑是放在ItemManager中实现的。不过值得注意的是，即使placeBid业务逻辑放在Item中，你仍然需要在ItemManager中简单的封装一层，以保证对placeBid业务逻辑进行事务的管理和持久化的触发。 <br /><br />这种模型是Martin Fowler所指的真正的domain model。在这种模型中，有三个业务逻辑方法：placeBid，loadItemById和findAll，现在的问题是哪个逻辑应该放在Item中，哪个逻辑应该放在ItemManager中。在我们这个例子中，placeBid放在Item中(但是ItemManager也需要对它进行简单的封装)，loadItemById和findAll是放在ItemManager中的。 <br /><br />切分的原则是什么呢？ Rod Johnson提出原则是“case by case”，可重用度高的，和domain object状态密切关联的放在Item中，可重用度低的，和domain object状态没有密切关联的放在ItemManager中。 <br /><br /><span style="COLOR: red">我提出的原则是：看业务方法是否显式的依赖持久化。</span><br /><br />Item的placeBid这个业务逻辑方法没有显式的对持久化ItemDao接口产生依赖，所以要放在Item中。<span style="COLOR: red">请注意，如果脱离了Hibernate这个持久化框架，Item这个domain object是可以进行单元测试的，他不依赖于Hibernate的持久化机制。它是一个独立的，可移植的，完整的，自包含的域对象</span>。 <br /><br />而loadItemById和findAll这两个业务逻辑方法是必须显式的对持久化ItemDao接口产生依赖，否则这个业务逻辑就无法完成。如果你要把这两个方法放在Item中，那么Item就无法脱离Hibernate框架，无法在Hibernate框架之外独立存在。<br /><br /><span class="postbody">第三种模型印象中好像是firebody或者是Archie提出的(也有可能不是，记不清楚了)，简单的来说，这种模型就是把第二种模型的domain object和business object合二为一了。所以ItemManager就不需要了，在这种模型下面，只有三个类，他们分别是： <br /><br />Item：包含了实体类信息，也包含了所有的业务逻辑 <br />ItemDao：持久化DAO接口类 <br />ItemDaoHibernateImpl：DAO接口的实现类 <br /><br />由于ItemDao和ItemDaoHibernateImpl和上面完全相同，就省略了。 <br /><br /></span><table cellspacing="1" cellpadding="3" width="90%" align="center" border="0"><tbody><tr><td><span class="genmed"><b>java代码: </b></span></td></tr><tr><td class="code"><div style="FONT-FAMILY: 'Courier New', Courier, monospace"><br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> Item <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">implements</span><span style="COLOR: #aaaadd" ?="">Serializable</span><span style="COLOR: #000000">{</span><br />    <span style="COLOR: #6666ff">//  所有的属性和getter/setter方法都省略</span><br />   <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">static</span> ItemDao itemDao; <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> setItemDao<span style="COLOR: #000000">(</span>ItemDao itemDao<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span>this.<span style="COLOR: #000000">itemDao</span> = itemDao;<span style="COLOR: #000000">}</span><br />    <br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">static</span> Item loadItemById<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Long</span> id<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span><span style="COLOR: #000000">(</span>Item<span style="COLOR: #000000">)</span> itemDao.<span style="COLOR: #000000">loadItemById</span><span style="COLOR: #000000">(</span>id<span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">static</span><span style="COLOR: #aaaadd" ?="">Collection</span> findAll<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span><span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">List</span><span style="COLOR: #000000">)</span> itemDao.<span style="COLOR: #000000">findAll</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br /><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> Bid placeBid<span style="COLOR: #000000">(</span>User bidder, MonetaryAmount bidAmount, <br />                    Bid currentMaxBid, Bid currentMinBid<span style="COLOR: #000000">)</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">throws</span> BusinessException <span style="COLOR: #000000">{</span><br />    <br />        <span style="COLOR: #6666ff">// Check highest bid (can also be a different Strategy (pattern))</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span>currentMaxBid != <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">null</span> &amp;&amp; currentMaxBid.<span style="COLOR: #000000">getAmount</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">compareTo</span><span style="COLOR: #000000">(</span>bidAmount<span style="COLOR: #000000">)</span> &gt; <span style="COLOR: #000000" ?="">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />                throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Bid too low."</span><span style="COLOR: #000000">)</span>; <br />        <span style="COLOR: #000000">}</span><br />        <br />        <span style="COLOR: #6666ff">// Auction is active</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> !state.<span style="COLOR: #000000">equals</span><span style="COLOR: #000000">(</span>ItemState.<span style="COLOR: #000000">ACTIVE</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />                throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Auction is not active yet."</span><span style="COLOR: #000000">)</span>; <br />        <br />        <span style="COLOR: #6666ff">// Auction still valid</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">if</span><span style="COLOR: #000000">(</span> this.<span style="COLOR: #000000">getEndDate</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">before</span><span style="COLOR: #000000">(</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">Date</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span><br />                throw <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> BusinessException<span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">"Can't place new bid, auction already ended."</span><span style="COLOR: #000000">)</span>; <br />        <br />        <span style="COLOR: #6666ff">// Create new Bid</span><br />        Bid newBid = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span> Bid<span style="COLOR: #000000">(</span>bidAmount, this, bidder<span style="COLOR: #000000">)</span>; <br />        <br />        <span style="COLOR: #6666ff">// Place bid for this Item</span><br />        this.<span style="COLOR: #000000">addBid</span><span style="COLOR: #000000">(</span>newBid<span style="COLOR: #000000">)</span>; <br />        itemDao.<span style="COLOR: #000000">update</span><span style="COLOR: #000000">(</span>this<span style="COLOR: #000000">)</span>;      <span style="COLOR: #6666ff">//  调用DAO进行显式持久化</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span> newBid; <br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div><br /></td></tr></tbody></table><span class="postbody"><br /><br />在这种模型中，所有的业务逻辑全部都在Item中，事务管理也在Item中实现。<br /><br /><span class="postbody">在上面三种模型之外，还有很多这三种模型的变种，例如partech的模型就是把第二种模型中的DAO和Manager三个类合并为一个类后形成的模型；例如frain....(id很长记不住)的模型就是把第三种模型的三个类完全合并为一个单类后形成的模型；例如Archie是把第三种模型的Item又分出来一些纯数据类(可能是，不确定)形成的一个模型。 <br /><br />但是不管怎么变，基本模型归纳起来就是上面的三种模型，下面分别简单评价一下： <br /><br />第一种模型绝大多数人都反对，因此反对理由我也不多讲了。但遗憾的是，我观察到的实际情形是，很多使用Hibernate的公司最后都是这种模型，这里面有很大的原因是很多公司的技术水平没有达到这种层次，所以导致了这种贫血模型的出现。从这一点来说，Martin Fowler的批评声音不是太响了，而是太弱了，还需要再继续呐喊。 <br /><br />第二种模型就是Martin Fowler一直主张的模型，实际上也是我一直在实际项目中采用这种模型。我没有看过Martin的POEAA，之所以能够自己摸索到这种模型，也是因为从02年我已经开始思考这个问题并且寻求解决方案了，但是当时没有看到Hibernate，那时候做的一个小型项目我已经按照这种模型来做了，但是由于没有O/R Mapping的支持，写到后来又不得不全部改成贫血的domain object，项目做完以后再继续找，随后就发现了Hibernate。当然，现在很多人一开始就是用Hibernate做项目，没有经历过我经历的那个阶段。 <br /><br />不过我觉得这种模型仍然不够完美，因为你还是需要一个业务逻辑层来封装所有的domain logic，这显得非常罗嗦，并且业务逻辑对象的接口也不够稳定。如果不考虑业务逻辑对象的重用性的话(业务逻辑对象的可重用性也不可能好)，很多人干脆就去掉了xxxManager这一层，在Web层的Action代码直接调用xxxDao，同时容器事务管理配置到Action这一层上来。Hibernate的caveatemptor就是这样架构的一个典型应用。 <br /><br />第三种模型是我很反对的一种模型，这种模型下面，Domain Object和DAO形成了双向依赖关系，无法脱离框架测试，并且业务逻辑层的服务也和持久层对象的状态耦合到了一起，会造成程序的高度的复杂性，很差的灵活性和糟糕的可维护性。也许将来技术进步导致的O/R Mapping管理下的domain object发展到足够的动态持久透明化的话，这种模型才会成为一个理想的选择。就像O/R Mapping的流行使得第二种模型成为了可能(O/R Mapping流行以前，我们只能用第一种模型，第二种模型那时候是不现实的)。</span><span class="postbody"></span><span class="gensmall"></span><br /><br /><span class="postbody">既然大家都统一了观点，那么就有了一个很好的讨论问题的基础了。Martin Fowler的Domain Model，或者说我们的第二种模型难道是完美无缺的吗？当然不是，接下来我就要分析一下它的不足，以及可能的解决办法，而这些都来源于我个人的实践探索。 <br /><br />在第二种模型中，我们可以清楚的把这4个类分为三层： <br /><br />1、实体类层，即Item，带有domain logic的domain object <br />2、DAO层，即ItemDao和ItemDaoHibernateImpl，抽象持久化操作的接口和实现类 <br />3、业务逻辑层，即ItemManager，接受容器事务控制，向Web层提供统一的服务调用 <br /><br />在这三层中我们大家可以看到，domain object和DAO都是非常稳定的层，其实原因也很简单，因为domain object是映射数据库字段的，数据库字段不会频繁变动，所以domain object也相对稳定，而面向数据库持久化编程的DAO层也不过就是CRUD而已，不会有更多的花样，所以也很稳定。 <br /><br />问题就在于这个充当business workflow facade的业务逻辑对象，它的变动是相当频繁的。<span style="COLOR: red">业务逻辑对象通常都是无状态的、受事务控制的、Singleton类</span>，我们可以考察一下业务逻辑对象都有哪几类业务逻辑方法： <br /><br /><span style="COLOR: red">第一类：DAO接口方法的代理</span>，就是上面例子中的loadItemById方法和findAll方法。 <br /><br />ItemManager之所以要代理这种类，目的有两个：<span style="COLOR: red">向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功能</span>。这两点都很容易理解，你不能既给Web层程序员提供xxxManager，也给他提供xxxDao，所以你需要用xxxManager封装xxxDao，在这里，充当了一个简单代理功能；而事务控制也是持久化方法必须的，事务可能需要跨越多个DAO方法调用，所以必须放在业务逻辑层，而不能放在DAO层。 <br /><br />但是必须看到，对于一个典型的web应用来说，绝大多数的业务逻辑都是简单的CRUD逻辑，所以这种情况下，针对每个DAO方法，xxxManager都需要提供一个对应的封装方法，这不但是非常枯燥的，也是令人感觉非常不好的。 <br /><br /><br /><span style="COLOR: red">第二类：domain logic的方法代理</span>。就是上面例子中placeBid方法。虽然Item已经有了placeBid方法，但是ItemManager仍然需要封装一下Item的placeBid，然后再提供一个简单封装之后的代理方法。 <br /><br />这和第一种情况类似，其原因也一样，也是为了给Web层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制。 <br /><br />同样，和第一种情况一样，针对每个domain logic方法，xxxManager都需要提供一个对应的封装方法，同样是枯燥的，令人不爽的。 <br /><br /><br /><span style="COLOR: red">第三类：需要多个domain object和DAO参与协作的business workflow</span>。这种情况是业务逻辑对象真正应该完成的职责。 <br /><br />在这个简单的例子中，没有涉及到这种情况，不过大家都可以想像的出来这种应用场景，因此不必举例说明了。 <br /><br />通过上面的分析可以看出，只有第三类业务逻辑方法才是业务逻辑对象真正应该承担的职责，而前两类业务逻辑方法都是“无奈之举”，不得不为之的事情，不但枯燥，而且令人沮丧。 <br /><br /><br /><br /><br />分析完了业务逻辑对象，我们再回头看一下domain object，我们要仔细考察一下domain logic的话，会发现domain logic也分为两类： <br /><br /><span style="COLOR: red">第一类：需要持久层框架隐式的实现透明持久化的domain logic</span>，例如Item的placeBid方法中的这一句： <br /></span><table cellspacing="1" cellpadding="3" width="90%" align="center" border="0"><tbody><tr><td><span class="genmed"><b>java代码: </b></span></td></tr><tr><td class="code"><div style="FONT-FAMILY: 'Courier New', Courier, monospace"><br />this.<span style="COLOR: #000000">getBids</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>.<span style="COLOR: #000000">add</span><span style="COLOR: #000000">(</span>newBid<span style="COLOR: #000000">)</span>;</div><br /></td></tr></tbody></table><span class="postbody"><br />上面已经着重提到，虽然这仅仅只是一个Java集合的添加新元素的操作，但是实际上通过事务的控制，会潜在的触发两条SQL：一条是insert一条记录到bid表，一条是更新item表相应的记录。如果我们让Item脱离Hibernate进行单元测试，它就是一个单纯的Java集合操作，如果我们把他加入到Hibernate框架中，他就会潜在的触发两条SQL，<span style="COLOR: red">这就是隐式的依赖于持久化的domain logic</span>。 <br />特别请注意的一点是：在没有Hibernate/JDO这类可以实现“透明的持久化”工具出现之前，这类domain logic是无法实现的。 <br /><br />对于这一类domain logic，业务逻辑对象必须提供相应的封装方法，以实现事务控制。 <br /><br /><br /><span style="COLOR: red">第二类：完全不依赖持久化的domain logic</span>，例如readonly例子中的Topic，如下： <br /><br /></span><table cellspacing="1" cellpadding="3" width="90%" align="center" border="0"><tbody><tr><td><span class="genmed"><b>java代码: </b></span></td></tr><tr><td class="code"><div style="FONT-FAMILY: 'Courier New', Courier, monospace"><br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">class</span> Topic <span style="COLOR: #000000">{</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">boolean</span> isAllowReply<span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />        <span style="COLOR: #aaaadd" ?="">Calendar</span> dueDate = <span style="COLOR: #aaaadd" ?="">Calendar</span>.<span style="COLOR: #000000">getInstance</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />        dueDate.<span style="COLOR: #000000">setTime</span><span style="COLOR: #000000">(</span>lastUpdatedTime<span style="COLOR: #000000">)</span>; <br />        dueDate.<span style="COLOR: #000000">add</span><span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">Calendar</span>.<span style="COLOR: #000000">DATE</span>, forum.<span style="COLOR: #000000">timeToLive</span><span style="COLOR: #000000">)</span>; <br />    <br />        <span style="COLOR: #aaaadd" ?="">Date</span> now = <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">new</span><span style="COLOR: #aaaadd" ?="">Date</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span>; <br />        <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">return</span> now.<span style="COLOR: #000000">after</span><span style="COLOR: #000000">(</span>dueDate.<span style="COLOR: #000000">getTime</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">)</span>; <br />    <span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span></div><br /></td></tr></tbody></table><span class="postbody"><br /><br />注意这个isAllowReply方法，他和持久化完全不发生一丁点关系。在实际的开发中，我们同样会遇到很多这种不需要持久化的业务逻辑(主要发生在日期运算、数值运算和枚举运算方面)，这种domain logic不管脱离不脱离所在的框架，它的行为都是一致的。对于这种domain logic，业务逻辑层并不需要提供封装方法，它可以适用于任何场合。</span></span></span></span>
<img src ="http://www.blogjava.net/jelver/aggbug/41009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-04-14 08:50 <a href="http://www.blogjava.net/jelver/articles/41009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML用例建模的慨念和应用</title><link>http://www.blogjava.net/jelver/articles/35894.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 17 Mar 2006 16:12:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/35894.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/35894.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/35894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/35894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/35894.html</trackback:ping><description><![CDATA[
		<span class="f14">一． UML简介<br /><br />　　UML（统一建模语言，Unified Modeling Language）是一种定义良好、易于表达、功能强大且普遍适用的可视化建模语言。它融入了软件工程领域的新思想、新方法和新技术。它的作用域不限于支持面向对象的分析与设计，还支持从需求分析开始的软件开发的全过程。在系统分析阶段，我们一般用UML来画很多图，主要包括用例图、状态图、类图、活动图、序列图、协作图、构建图、配置图等等，要画哪些图要根据具体情况而定。其实简单的理解，也是个人的理解，UML的作用就是用很多图从静态和动态方面来全面描述我们将要开发的系统。<br /><br />　　二． 用例建模简介<br /><br />　　用例建模是UML建模的一部分，在我眼里，它也是UML里最基础的部分。用例建模的最主要功能就是用来表达系统的功能性需求或行为。<br /><br />　　依我的理解用例建模可分为用例图和用例描述。用例图由参与者（Actor）、用例（Use Case）、系统边界、箭头组成，用画图的方法来完成。用例描述用来详细描述用例图中每个用例，用文本文档来完成。<br /><br />　　1． 用例图<br /><br />　　参与者不是特指人，是指系统以外的，在使用系统或与系统交互中所扮演的角色。因此参与者可以是人，可以是事物，也可以是时间或其他系统等等。还有一点要注意的是，参与者不是指人或事物本身，而是表示人或事物当时所扮演的角色。比如小明是图书馆的管理员，他参与图书馆管理系统的交互，这时他既可以作为管理员这个角色参与管理，也可以作为借书者向图书馆借书，在这里小明扮演了两个角色，是两个不同的参与者。参与者在画图中用简笔人物画来表示，人物下面附上参与者的名称。<br /><br /><img align="center" border="1" hspace="3" onerror="this.src='http://www.yesky.com/image20010518/128919.gif';" src="http://www.yesky.com/image20010518/128919.gif" vspace="1" /><br /><br />　　用例是对包括变量在内的一组动作序列的描述，系统执行这些动作，并产生传递特定参与者的价值的可观察结果。这是UML对用例的正式定义，对我们初学者可能有点难懂。我们可以这样去理解，用例是参与者想要系统做的事情。对于对用例的命名，我们可以给用例取一个简单、描述性的名称，一般为带有动作性的词。用例在画图中用椭圆来表示，椭圆下面附上用例的名称。<br /><br /><img align="center" border="1" hspace="3" onerror="this.src='http://www.yesky.com/image20010518/128920.gif';" src="http://www.yesky.com/image20010518/128920.gif" vspace="1" /><br /><br />　　系统边界是用来表示正在建模系统的边界。边界内表示系统的组成部分，边界外表示系统外部。系统边界在画图中方框来表示，同时附上系统的名称，参与者画在边界的外面，用例画在边界里面。因为系统边界的作用有时候不是很明显，所以我个人理解，在画图时可省略。<br /><br />　　箭头用来表示参与者和系统通过相互发送信号或消息进行交互的关联关系。箭头尾部用来表示启动交互的一方，箭头头部用来表示被启动的一方，其中用例总是要由参与者来启动。<br /><br />　　2． 用例描述<br /><br />　　用例图只是简单地用图描述了一下系统，但对于每个用例，我们还需要有详细的说明，这样就可以让别人对这个系统有一个更加详细的了解，这时我们就需要写用例描述。<br /><br />　　对于用例描述的内容，一般没有硬性规定的格式，但一些必须或者重要的内容还是必须要写进用例描述里面的。用例描述一般包括：简要描述（说明）、前置（前提）条件、基本事件流、其他事件流、异常事件流、后置（事后）条件等等。下面说说各个部分的意思：<br /><br />　　简要描述：对用例的角色、目的的简要描述；<br /><br />　　前置条件：执行用例之前系统必须要处于的状态，或者要满足的条件；<br /><br />　　基本事件流：描述该用例的基本流程，指每个流程都“正常”运作时所发生的事情，没有任何备选流和异常流，而只有最有可能发生的事件流；<br /><br />　　其他事件流：表示这个行为或流程是可选的或备选的，并不是总要总要执行它们；<br /><br />　　异常事件流：表示发生了某些非正常的事情所要执行的流程；<br /><br />　　后置条件：用例一旦执行后系统所处的状态；<br /><br /><script><![CDATA[mbbs=1;]]&gt;</script><br /><br />UML的作用就是用很多图从静态和动态方面来全面描述我们将要开发的系统</span>
		<br />三． 用例图和用例描述设计实例<br /><br />　　这里用我开发的一个家教网站来简单的分析用例图的画法和用例描述的写法。这个网站我用UML完整的分析一下，以下我提取了用例图和用例描述的部分。这个家教网站分为前台客户系统和后台管理系统。<br /><br />　　前台客户系统的用例图如下：<br /><br /><img align="center" border="1" hspace="3" onerror="this.src='http://www.yesky.com/image20010518/128921.gif';" src="http://www.yesky.com/image20010518/128921.gif" vspace="1" /><br /><br />　　后台管理系统用例图如下：<br /><br /><img align="center" border="1" hspace="3" onerror="this.src='http://www.yesky.com/image20010518/128922.gif';" src="http://www.yesky.com/image20010518/128922.gif" vspace="1" /><br /><br />　　对于用例描述，篇幅有限，我在这里只列了后台管理系统中的网站公告发布这个用例的描述。如下：<br /><br /><table border="1" cellspacing="0" width="100%"><tbody><tr><td>用例名称：网站公告发布</td></tr><tr><td>用例标识号：202</td></tr><tr><td>参与者：负责人</td></tr><tr><td>简要说明：<br />　　负责人用来填写和修改家教网站首页的公告，公告最终显示在家教网站的首页上。</td></tr><tr><td>前置条件：<br />　　负责人已经登陆家教网站管理系统</td></tr><tr><td>基本事件流：<br />　1． 负责人鼠标点击“修改公告”按钮<br />　2． 系统出现一个文本框，显示着原来的公告内容<br />　3． 负责人可以在文本框上修改公告，也可以完全删除，重新写新的公告<br />　4． 负责人编辑完文本框，按“提交”按钮，首页公告就被修改<br />　5． 用例终止</td></tr><tr><td>其他事件流A1：<br />　在按“提交”按钮之前，负责人随时可以按“返回”按钮，文本框的任何修改内容都不会影响网站首页的公告</td></tr><tr><td>异常事件流：<br />　1． 提示错误信息，负责人确认<br />　2． 返回到管理系统主页面</td></tr><tr><td>后置条件：<br />　网站首页的公告信息被修改</td></tr><tr><td>注释：无</td></tr></tbody></table><br />　　<img src ="http://www.blogjava.net/jelver/aggbug/35894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-18 00:12 <a href="http://www.blogjava.net/jelver/articles/35894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>建模工具Rose的学习2）</title><link>http://www.blogjava.net/jelver/articles/35893.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 17 Mar 2006 16:09:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/35893.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/35893.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/35893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/35893.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/35893.html</trackback:ping><description><![CDATA[概述 
<p>　　在这个面向对象应用程序开发不断变化的时代，在合理时间内开发和管理高质量应用程序变得越来越困难。为了面对这种挑战，制定出每个公司都能使用的通用对象模型语言，统一建模语言（UML）。UML是信息技术行业的蓝图，是详细描述系统结构的方法。利用这个蓝图，我们越来越容易建立和维护系统，保证系统能适应需求的改变。一个系统的模型建得好，就为满足用户需求、保证系统的稳定性和质量、提高系统的扩展性打下了良好的基础。ROSE是用UML快速开发应用程序的工具之一，它是一个面向对象的建模工具。 </p><p>UML统一建模语言 </p><p>　　UML，Unified Modeling Language，统一建模语言，是一种面向对象的建模语言，它的主要作用是帮助我们对软件系统进行面向对象的描述和建模，它可以描述这个软件开发过程从需求分析直到实现和测试的全过程。UML通过建立各种类、类之间的关联、类/对象怎样相互配合实现系统的动态行为等成分（这些都称为模型元素）来组建整个模型，刻画客观世界。UML提供了各种图形，比如Use Case图、类图、顺序图、协作图、状态图等，来把这些模型元素及其关系可视化，让人们可以清楚容易的理解模型。我们可以从多个视角来考察模型，从而更加全面的了解模型，这样同一个模型元素可能会出现在多个图中，对应多个图形元素。 <br /></p><p>　　由视图view，图diagram，模型元素model element和通用机制general mechanism等几个部分组成 .视图是表达系统的某一方面特征的UML建模元素的子集，由多个图构成，是在某一个抽象层上，对系统的抽象表示.图是模型元素集的图形表示，通常为弧（关系）和顶点（其他模型元素）相互连接构成的.模型元素代表面向对象中的类、对象、消息和关系等概念，是构成图的最基本的常用概念.通用机制用于表示其它信息，比如注释、模型元素的语义等。另外，它还提供扩展机制，使UML语言能够适应一个特殊的方法（或过程），或扩充至一个组织或用户. <br /></p><p>　　UML是用来描述模型的，用模型来描述系统的结构或静态特征，以及行为或动态特征。从不同的视角为系统的构架建模，形成系统的不同视图（VIEW）。 <br /></p><p>　　用例视图(use case view)，强调从用户的角度看到的或需要的系统功能，是被称为参与者的外部用户所能观察到的系统功能的模型图； <br /></p><p>　　逻辑视图(logical view)，展现系统的静态或结构组成及特征，也称为结构模型视图(structural model view)或静态视图（static view）； <br /></p><p>　　并发视图(concurrent view)，体现了系统的动态或行为特征，也称为行为模型视图（behavioral model view）、动态视图(dynamic view)； <br /></p><p>　　组件视图(component view)，体现了系统实现的结构和行为特征，也称为实现模型视图(implementation model view) ； <br /></p><p>　　配置视图(deployment view)，体现了系统实现环境的结构和行为特征，也称为环境模型视图（environment model view）或物理视图(physical view)。 </p><p>建模工具Rose 之游 </p><p>　　ROSE是美国Rational公司的面向对象建模工具，利用这个工具，我们可以建立用UML描述的软件系统的模型，而且可以自动生成和维护C++、Java、VB、Oracle等语言和系统的代码。 <br /></p><p>　　ROSE是个菜单驱动应用程序，用工具栏帮助使用常用特性。它的界面分为三个部分--Browser窗口、Diagram窗口和Document窗口。Browser窗口用来浏览、创建、删除和修改模型中的模型元素；Diagram窗口用来显示和创作模型的各种图；而Document窗口则是用来显示和书写各个模型元素的文档注释。 </p><p align="center"><img height="333" src="http://www.ddvip.net/program/uml/index3/img/rosexx_1.gif" width="412" /></p><p align="center">Rose界面 <br /></p><p>　　Rose模型的四个视图是Use Case视图 、Logical视图、Component视图和Deployment视图。每个视图针对不同对象，具有不同用途。Use Case视图包括系统中的所有角色、案例和Use Case图，还包括一些Sequence图和Collaboration图。 <br /></p><p align="center"><img height="280" src="http://www.ddvip.net/program/uml/index3/img/rosexx_2.gif" width="181" /></p><p align="center">Use Case视图 <br /></p><p>　　Logical视图关注系统如何实现使用案例中提到的功能。它提供系统的详细图形，描述组件间如何关联。除其它内容之外，Logical视图还包括需要的特定类、Class图和State Transition 图。利用这些细节元素，开发人员可以构造系统的详细设计。 </p><p align="center"><img height="308" src="http://www.ddvip.net/program/uml/index3/img/rosexx_3.gif" width="181" /></p><p align="center"><br />Logical视图 <br /></p><p>　　Component视图包括模型代码库、执行库和其它组件的信息。组件是代码的实际模块。Component视图的主要用户是负责控制代码和编译部署应用程序的人。有些组件是代码库，有些组件是运行组件，如执行文件或动态链接库（DLL）文件。 <br /></p><p>　　Collaboration图关注系统的部署，可能与系统的逻辑结构不同。整个小组都用Collaboration图了解系统部署，但用户是发布应用程序的人员。 </p><p>Rose的九种图 <br /></p><p>　　用例图use case diagram，描述系统功能 <br />　　 类图class diagram，描述系统的静态结构 <br />　　 对象图object diagram，描述系统在某个时刻的静态结构 <br />　　 序列图sequence diagram，按时间顺序描述系统元素间的交互 <br />　　 协作图Collaboration diagram，按照时间和空间顺序描述系统元素间的交互和它们之间的关系 <br />　　 状态图state diagram，描述了系统元素的状态条件和响应 <br />　　 活动图activity diagram，描述了系统元素的活动 <br />　　 组件图component diagram，描述了实现系统的元素的组织 <br />　　 配置图deployment diagram，描述了环境元素的配置，并把实现系统的元素映射到配置上 <br /></p><p>　　根据它们在不同架构视图的应用，可以把9种图分成： <br /></p><p>　　用户模型视图：用例图 <br />　　 结构模型视图：类图、对象图 <br />　　 行为模型视图：序列图、协作图、状态图、活动图（动态图） <br />　　 实现模型视图：组件图 <br />　　 环境模型视图：配置图 </p><img src ="http://www.blogjava.net/jelver/aggbug/35893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-18 00:09 <a href="http://www.blogjava.net/jelver/articles/35893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>建模工具Rose的学习</title><link>http://www.blogjava.net/jelver/articles/35892.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 17 Mar 2006 16:08:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/35892.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/35892.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/35892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/35892.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/35892.html</trackback:ping><description><![CDATA[在随着面向对象的程序设计的广泛应用，可视化编程遍地开花的今天，编程工作人员的地位一再被动摇，早以不再作为开发中的主流，而软件工程的应用以作为软件开发的质量和效率的重要见证已越来越被重视，针对早期的结构化建模工具的明显不足，ROSE吸取众多建模工具的优点，排除其不足，采用面向对象的成熟技术和双向工程的技巧，为提高软件开发的效率，保证软件开发的质量和可维护性作出了巨大的贡献。 <br />软件工程概述 <br />　　 软件开发是一套关于软件开发各阶段的定义、任务、作用的建立在理论上的一门工程学科。它为解决软件危机，指导人们利用科学、有效的方法来开发软件，提高及保证软件开发的效率和质量取到了一定的作用。 软件开发过程：需求分析（开始阶段）--概要设计（静态结构）--详细设计（动态结构） --编码-测试-维护 <br />结构化模型设计方法 <br />A．E-R图（实体关系图） <br />　　 实体：客观存在并可区分的事物。 <br />　　 属性：实体所具有的某种特性，一个实体可以有多个属性。 <br />　　 关系：实体之间的对应关系，可分为1：1联系、1：n联系、m：n联系 <br /><img height="530" src="http://www.ddvip.net/program/uml/index3/img/rosexx.gif" width="400" /><br />B．数据流图 <br /><img height="241" src="http://www.ddvip.net/program/uml/index3/img/rosexx1.gif" width="538" /><br />C．功能模块图 <br /><img height="252" src="http://www.ddvip.net/program/uml/index3/img/rosexx2.gif" width="370" /><br />结构化模型的不足 <br />　　 传统的结构化模型的设计所建立的模型不能反应源代码，与程序设计脱节。模型与代码几乎没什么关系。这样的模型不能生成代码，代码更不能生成模型，模型大多是画给领导看或拿出作掩盖。所以不能保证软件的质量，更不易软件的维护，没什么约束力也没有检测的标准，它的弊端是显于易见的。 <br />面向对象的模型设计方法 <br />　　 定义：利用面向对象方法，把应用程序分成许多小块（对象），这些对象是独立的，然后组合这些对象，建立程序。 <br />　　 特点：包装、继承、多态。 <br />　　 常用的建模工具：PlayCase, Rational ROSE, Computer Association BPWin , Computer Association ERWin, Oracle Designer/2000, Sybase PowerDesigner <br />UML语言概述 <br />　　 定义：一种面向对象的统一建模语言。 <br />　　 作用：帮助我们对软件系统进行面向对象的和建模。 <br />　　 核心：类，类之间的关系。 <br />　　 建模：通过将用户的业务震需求映射为代码，保证代码满足这些需求，代码能方便地回溯需求，这个过程叫建模。 <br />ROSE建模工具 <br />　　 定义：是一种分析和设计面向对象的建模工具。 <br />　　 作用：利用ROSE这个工具，我们可以建立用UML的软件系统的模型，面目可以自动生成和维护C++、JAVA、VB、PB、ORACLE等语言和系统的代码。 <br />　　 核心：七大框图 <br />　　 1. Use-Case Diagrams（用例框图） <br />　　 2. sequence diagram （顺序框图） <br />　　 3. Collaboration diagram （协作框图） <br />　　 4. Class diagram （类框图） <br />　　 5. State Transition diagram （状态框图） <br />　　 6. Component diagram （组件框图） <br />　　 7. Deployment diagram （扩展框图） <br />　　 下面结合软件工程知识、利用ROSE建模工具，本人在开发电力部们的"110KV标准设计图文管理系统"中所用到的ROSE模型及对ROSE在开发实践中的剖析 <br />一、 需求分析阶段 <br />　　 任务：建立用户需求和功能模块，确定系统中的角色和使用案例。利用ROSE，生成角色，使用案例和生成用例图 <br />所用到的框图： <br />　　 1.Use-Case Diagrams：显示使用案例（表示系统功能）与角色（人或系统）间的交互。如下图： <br /><img height="347" src="http://www.ddvip.net/program/uml/index3/img/rosexx3.gif" width="450" /><br />　　 Use Case（用例）：在不展现一个系统或系统内部结构的情况下，对系统或系统的连贯的功能单元的定义和描述。 <br />角色：使用软件的人或外部系统本身。 <br />2. sequence diagram <br />　　 按时间先后顺序，从上到下分析使用案例，确定案例的处理流程。如下图： <br /><img height="566" src="http://www.ddvip.net/program/uml/index3/img/rosexx4.gif" width="493" /><br />3 Collaboration diagram ： <br />　　 确定对象之间的关系的处理过程的分析流程。如下图： <br /><img height="396" src="http://www.ddvip.net/program/uml/index3/img/rosexx5.gif" width="429" /><br />二、 概要设计阶段 <br />　　 任务：通过分析Use-Case Diagrams ，得到所用到的类，分析这些类的属性、操作和它们之间的关系。 <br />　　 所用到的框图： <br />1.Class Diagrams. <br />　　 显示系统中类与类之间的交互。 <br /><img height="338" src="http://www.ddvip.net/program/uml/index3/img/rosexx6.gif" width="203" /><br />2.包：具有一些共性的类组合在一起的图。 <br /><img height="180" src="http://www.ddvip.net/program/uml/index3/img/rosexx7.gif" width="383" /><br /><br />三、 详细设计阶段 <br />　　 任务：细化和个性Use-Case的描述 ，如类的操作和对象之间的消息相对应，填充参数及复杂的类的设计。 <br />　　 所用到的框图： <br />1.Class Diagrams <br />2.State Diagrams:显示一个对象从生成到删除的生命周期。 <br />四、 编码和测试阶段 <br />　　 任务：进行软件的开发和测试，生成组件框图。 <br />　　 组件：表示代码的物理模块。 <br />　　 组件框图：表示系统中的组件及相互依赖性。 <br />　　 Delpoyment Diagrams:显示网络中的物理布局和各种组件的位置。 <br /><img height="231" src="http://www.ddvip.net/program/uml/index3/img/rosexx8.gif" width="511" /><br />双向工程 <br />　　 1.生成代码：根据选择开发应用程序的语言生成对应的程序的代码。 <br />　　 步骤：检查模型-生成组件-将类映射组件-设置代码生成属性-选择类、组件和包-生成代码 <br />　　 2.逆向转出工程：根据选择开发应用程序的语言生成对应的程序的代码。 <br />　　 步骤：检查模型-生成组件-将类映射组件-设置代码生成属性-选择类、组件和包-生成代码 <img src ="http://www.blogjava.net/jelver/aggbug/35892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-18 00:08 <a href="http://www.blogjava.net/jelver/articles/35892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML的用例(Use Case)概念分析及实例 </title><link>http://www.blogjava.net/jelver/articles/35299.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Tue, 14 Mar 2006 13:09:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/35299.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/35299.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/35299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/35299.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/35299.html</trackback:ping><description><![CDATA[<TABLE border=0 cellPadding=0 cellSpacing=0 height="100%" style="TABLE-LAYOUT: fixed; word-wrap: break-word" width="100%">
<TBODY>
<TR>
<TD vAlign=top><A href="http://bbs.softat.org/misc.php?action=viewratings&amp;tid=66202&amp;pid=66399" name=pid66399 alt="查看评分记录"></A><SPAN class=smalltxt><SPAN class=bold>UML的用例(Use Case)概念分析及实例</SPAN></SPAN><BR><SPAN style="FONT-SIZE: 12px"><SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体"><BR>文</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">/</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">登峰　</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><CHSDATE w:st="on" isrocdate="False" islunardate="False" day="25" month="2" year="2005"></CHSDATE><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">2005-02-25</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 6pt; mso-pagination: widow-orphan; mso-char-indent-count: .5"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">在</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">UML</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">中</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">use case</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">似乎最簡單的，</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">用例建模的最主要功能就是用来表达系统的功能性需求或行为，依我的理解用例建模可分为用例图和用例描述。用例图由参与者（</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">Actor</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">）、用例（</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">Use Case</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">）、系统边界、箭头组成，用画图的方法来完成。用例描述用来详细描述用例图中每个用例，用文本文档来完成，以及由箭头所组成的各种关系，包括泛化，包含，扩展等。本文准备向大家介绍以下内容</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">,</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">所有图示均用</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">PowerDesigner</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">所画</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">. </SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">用况</SPAN><SPAN style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"> <SPAN lang=EN-US>
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">参与者</SPAN><SPAN style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"> <SPAN lang=EN-US>
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">泛化</SPAN><SPAN style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"> <SPAN lang=EN-US>
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&lt;&lt;use&gt;&gt; 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&lt;&lt;include&gt;&gt; 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&lt;&lt;extend&gt;&gt; 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Wingdings; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings">u</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-fareast-font-family: Wingdings; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">用例描述</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp; 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: 宋体">１．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">用况（</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">use case</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">）</SPAN></B><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp;</SPAN></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><IMG alt="" height=115 src="http://blog.csdn.net/images/blog_csdn_net/Korny/1.JPG" width=387>　</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: Arial">图１</SPAN><SPAN style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman"> </FONT></SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">用况图</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp; </SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">是对一组动作序列（其中包括它的变体）的描述，系统执行该动作为执行此动作的参与者产生一个可观察的结果值。比如你使用计算器，这里可以把计算器看作为用况，参与者是登峰，登峰按了３＋３（用况执行的序列），计算机器返回一个结果６。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp;</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> </SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: 宋体">２．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">参与者</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt">(Actor) </SPAN></B></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt"></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
<P><IMG alt="" height=68 src="http://blog.csdn.net/images/blog_csdn_net/Korny/1.1.JPG" width=76></P></SPAN></B>
<P></P>
<P><IMG alt="" height=68 src="http://blog.csdn.net/images/blog_csdn_net/Korny/1.1.JPG" width=76></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;</SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　<SPAN lang=EN-US>&nbsp; 
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">参与者不是特指人，是指系统以外的，在使用系统或与系统交互中所扮演的角色。因此参与者可以是人，可以是事物，也可以是时间或其他系统等等。还有一点要注意的是，参与者不是指人或事物本身，而是表示人或事物当时所扮演的角色。比如小明是图书馆的管理员，他参与图书馆管理系统的交互，这时他既可以作为管理员这个角色参与管理，也可以作为借书者向图书馆借书，在这里小明扮演了两个角色，是两个不同的参与者。参与者在画图中用简笔人物画来表示，人物下面附上参与者的名称。</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-size: 10.5pt"><BR><BR><BR></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-size: 10.5pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: left; TEXT-INDENT: -21pt; mso-pagination: widow-orphan; tab-stops: list 21.0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: 宋体">３．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: black; FONT-SIZE: 7pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial; mso-bidi-font-size: 10.5pt">泛化</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-size: 10.5pt"> <SPAN lang=EN-US>
<P></P></SPAN></SPAN></B>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">泛化和类中的泛化概念是一样的，子用况继承父用况的行为和含义，还可以增加或覆盖父用况的行为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">子用况可以出现在任何父用况出现的位置（父和子均有具体的实例）。下面给出两种图示来说明泛化的概念和含义</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　<SPAN lang=EN-US> 
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体"><IMG alt="" height=230 src="http://blog.csdn.net/images/blog_csdn_net/Korny/2.JPG" width=112>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG alt="" height=186 src="http://blog.csdn.net/images/blog_csdn_net/Korny/3.JPG" width=341> 
<P align=right class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan">&nbsp;&nbsp;&nbsp;&nbsp; </P></SPAN>
<P></P>
<P align=right class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan">&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P></P>
<P align=right class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan">&nbsp;&nbsp;&nbsp;&nbsp; </P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">图２　含义继承</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">图３　行为继承</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;</FONT></SPAN><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">４．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;user&gt;&gt; 
<P></P></FONT></SPAN></B>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-layout-grid-align: none"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;use&gt;&gt;: </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">其</SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-hansi-font-family: TimesNewRomanPSMT; mso-bidi-font-family: 宋体; mso-bidi-font-size: 10.5pt">关系非常象一个函数调用或一个子过程以这种方式使用的用例称为抽 <SPAN lang=EN-US>
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-layout-grid-align: none"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-hansi-font-family: TimesNewRomanPSMT; mso-bidi-font-family: 宋体">象用例因为它不能单独存在而必须被其它用例使用，请看下图 <SPAN lang=EN-US>
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-layout-grid-align: none"><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp; 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-layout-grid-align: none"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　<IMG alt="" height=221 src="http://blog.csdn.net/images/blog_csdn_net/Korny/4.JPG" width=353><SPAN lang=EN-US> 
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">　　　　　　　　　　　图４　使用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;use&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">示例</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp;</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN></FONT>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp;</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN></FONT>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">５．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;include&gt;&gt; 
<P></P></FONT></SPAN></B>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; TEXT-INDENT: 21pt; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">怎么解释这个定义呢？　还是说明一下它的功能吧，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;include&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">可以把几个用例的公共步骤分离出来成为一个单独的被包含用例。学过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">C</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">的朋友知道它的含义了吧。呵呵</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">好的，定义都已经知道了，下面用一个示例来加深大家的印象。假如有个人事系统，经理可以查看员工的信息，并可以增加，修改和删除，但每次执行这三个操作时，都要定位到相应的员工，即先查询定位到要操作的员工。图５给出了这种表述的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">use case </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">图</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">,</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">请理解</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;include&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">的含义</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-font-kerning: 0pt">&nbsp;<IMG alt="" height=204 src="http://blog.csdn.net/images/blog_csdn_net/Korny/5.JPG" width=497></SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN></FONT>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">　</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">　图５　</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;include&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">的用法</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">6</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">．</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;extend&gt;&gt; 
<P></P></FONT></SPAN></B>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>&lt;&lt;extend&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">为已存在用例添加新的行为提供了一种方法。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">基础用例提供了一组扩展点（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">extend points</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">），扩展点是钩子，在此可以添加新的行为，扩展用例提供了一组插入片段，这些片段可被插入到基础用例的钩子位置。需要注意的是基础用例不知道扩展用例的任何细节，它仅为扩展用例提供了钩子。这与</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&lt;&lt;include&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">不同，此时如果没有被包含用例，客户用例将不完整。图６说明了主述文字描述</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　<SPAN lang=EN-US> 
<P></P></SPAN></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: Arial">　　　　　　　　　　　　 <IMG alt="" height=206 src="http://blog.csdn.net/images/blog_csdn_net/Korny/6.JPG" width=461></SPAN></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">&nbsp;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: Arial">　　　　　　　　　　　　图６</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><FONT face="Times New Roman"> &lt;&lt;extend&gt;&gt;</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: Arial">的用法</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">７．用例描述</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">当然用例描述就是对用例的文字性说明。具体要描述哪些项，这里就不多说了，给大家一个具体示例一看就明白。假如有个家教网，下面只是一个抽象片段。主要是为了说明用例描述的含义。</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt"> </SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
<P></P></SPAN></FONT>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><FONT face="Times New Roman"><SPAN lang=EN-US style="FONT-SIZE: 12pt; mso-font-kerning: 0pt">&nbsp; <IMG alt="" height=124 src="http://blog.csdn.net/images/blog_csdn_net/Korny/7.JPG" width=267></SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN></FONT>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt; mso-font-kerning: 0pt; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-bidi-font-family: Arial">　</SPAN><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><SPAN lang=EN-US style="FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-font-kerning: 0pt">
<P>&nbsp;</P></SPAN>
<P></P>
<P>&nbsp;</P>
<P></P>
<P align=left class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan"><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 宋体">下面就是用例网站公告发布的用例描述</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体; FONT-SIZE: 12pt; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 
<P></P></SPAN>
<P></P>
<P></P>
<P></P>
<P>&nbsp;</P></SPAN></SPAN></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jelver/aggbug/35299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-14 21:09 <a href="http://www.blogjava.net/jelver/articles/35299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对象关系数据库之间的映射</title><link>http://www.blogjava.net/jelver/articles/35292.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Tue, 14 Mar 2006 12:41:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/35292.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/35292.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/35292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/35292.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/35292.html</trackback:ping><description><![CDATA[对象关系数据库之间的映射<BR><BR>
<SCRIPT type=text/javascript><!--
google_ad_client = "pub-1342436837907284";
google_ad_width = 468;     
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_channel ="2319024336";
google_color_border = "F8F9FC";
google_color_bg = "F8F9FC";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
//--></SCRIPT>

<SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript>
</SCRIPT>
<SPAN style="FONT-SIZE: 12px">为什么对象-关系数据库的映射对于现代开发者是一件大事呢？一方面，对象技术（例如 Java 技术）是应用于新软件系统开发的最常见的环境。另外，关系数据库仍然是许多人都青睐的持久信息存储方法，并且在较长时间内这种情况不太会改变。请继续读下去，了解如何使用这种技术。<BR><BR>
<P>为什么要写有关对象-关系数据库之间的映射的文章呢？因为在对象范例和关系范例之间“阻抗不匹配”。对象范例基于软件工程的一些原理，例如耦合、聚合和封装，而关系范例则基于数学原理，特别是集合论的原理。两种不同的理论基础导致各自有不同的优缺点。而且，对象范例侧重于从包含数据和行为的对象中构建应用程序，而关系范例则主要针对数据的存储。当为访问而寻找一种合适的方法时，“阻抗不匹配”就成了主要矛盾：使用对象范例，您是通过它们的关系来访问对象，而使用关系范例，则通过复制数据来联接表中的行。这种基本的差异导致两种范例的结合并不理想，不过话说回来，本来就预料到会有一些问题。使对象-关系数据库之间的映射成功的一个秘诀就是理解这两种范例和它们的差异，然后基于这些认识来进行明智的取舍。</P>
<P>本文应该能够消除现今开发周期中一些普遍共有的误解，对对象-关系数据库之间映射所涉及到的一些问题提供了切合实际的看法。这些策略基于我的开发经验，项目范围从小到大，涉及金融、销售、军事、远程通信和外购等行业。我已对使用 C++、 Smalltalk、Visual Basic 和 Java 语言编写的应用程序应用了这些原则。</P><A id=1 name=1></A>
<P><STRONG class=subhead>如何将对象映射成关系数据库</STRONG><BR>在这一节中，我会描述一些将对象成功映射成关系数据库所需的基本技术。</P>
<UL>
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#1a">将属性映射成列</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#1c">在关系数据库中实现继承</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#1b">将类映射成表</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#4">映射关联、聚合和组合</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#6">实现关系</A> </LI></UL><A id=1a name=1a></A>
<P><STRONG class=subhead>将属性映射成列</STRONG><BR>类属性将映射成关系数据库中的零或几列。要记住，并不是所有属性都是持久的。例如， <CODE><FONT face=新宋体>Invoice</FONT></CODE> 类会有 <CODE><FONT face=新宋体>grandTotal</FONT></CODE> 属性，这个属性由其实例在计算时使用，但它不保存到数据库中。而且，某些对象属性本身就是对象，例如 <CODE><FONT face=新宋体>Course</FONT></CODE> 对象有一个作为属性的 <CODE><FONT face=新宋体>TextBook</FONT></CODE> 实例，它映射为数据库中的几列（实际上，很有可能 <CODE><FONT face=新宋体>TextBook</FONT></CODE> 类本身就将映射成一个或多个表）。重要的是，这是一个递归定义：有时属性将映射成零或者多列。也有可能将几个属性映射成表中的单一列。例如，代表美国邮递区号代码的类可以有三个数字属性，每个都表示完整邮政编号代码中的每一部分，而邮政编号代码可以在地址表中作为单一的列存储。</P><A id=1c name=1c></A>
<P><STRONG class=subhead>在关系数据库中实现继承</STRONG><BR>在将对象保存到关系数据库中时，继承的概念中发生几个有趣的问题。（请参阅<A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#resources">参考资料</A>中的 "Building Object Applications That Work"。）问题从根本上归结为解释如何在您的持久模型中组织继承的属性。解决这个难题所用的方法会对系统设计有很大影响。将继承映射到关系数据库中有三种基本解决办法，为更好地理解它们，我将讨论在图 1 中显示的映射类图表的优缺点。为简化问题，我没有为类的所有属性都建模；也没有为其完整签名或任何类方法建模。</P>
<P><A id=art1 name=art1><STRONG>图 1. 简单类层次结构的 UML 类示意图</STRONG><BR><IMG alt="" border=0 height=167 src="http://bbs.softat.org/ArticleImages/20031212194839136.jpg" width=391 pop="图 1. 简单类层次结构的 UML 类示意图" valign="top"></A></P><A id=1b name=1b></A>
<P><STRONG class=subhead>将类映射成表</STRONG><BR>类到表的映射通常不是直接的。除了非常简单的数据库以外，您不会有类到表的一对一映射。在以下章节中，我将讨论为关系数据库实现继承结构的三种策略：</P>
<UL>
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#1d">整个类层次结构使用一个数据实体</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#1e">每个具体类使用一个数据实体</A> 
<LI><A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#2">每个类使用一个数据实体</A> </LI></UL><BR><BR><A id=1d name=1d></A>
<P><B>整个类层次结构使用一个数据实体</B><BR>使用这种方法，您可以将一个完整类层次结构映射成一个数据实体，而层次结构中所有类的所有属性都存储在这个实体中。图 2 描述了采取这个方法时图 1 的类层次结构的持久模型。请注意，为表的主键引入了一个 <CODE><FONT face=新宋体>personOID</FONT></CODE> 列 - 我在所有解决方案中都使用 OID （没有商业含义的标识，又称替代键），只是为了保持一致和使用我所知道的向数据实体分配键的最好办法。</P>
<P><A id=art1 name=art1><STRONG>图 2. 将类层次结构映射成单一数据实体</STRONG><BR><IMG alt="图 2. 将类层次结构映射为单一数据实体" border=0 height=140 src="http://bbs.softat.org/ArticleImages/20031212194839764.jpg" width=218 valign="top"></A></P>
<P>这种方法的优点是简单，因为所需的所有人员数据都可以在一张表中找到，所以在人们更改角色时支持多态性，并且使用这种方法，专门报告（为一小组用户特定目的所执行的报告，这些用户通常自己写报告）也非常简单。缺点是每次在类层次结构的任何地方添加一个新属性时都必须将一个新属性添加到表中。这增加了类层次结构中的耦合 - 如果在添加一个属性时有任何错误，除获得新属性的类的子类外，还可能影响到层次结构中的所有类。它还可能浪费数据库中的许多空间。我还必须添加 <CODE><FONT face=新宋体>objectType</FONT></CODE> 列来表明行代表的是学生、教授还是其它类型的人员。在人们具有单一角色时这种方法很有效，但如果他们有多个角色（例如，一个人既是学生又是教授），很快就会失效。</P><A id=1e name=1e></A>
<P><B>每个具体类使用一个数据实体</B><BR>使用这种方法，每个数据实体就既包含属性又包含它所表示的类继承的属性。图 3 描述了采取这个方法时图 1 的类层次结构的持久模型。有与 <CODE><FONT face=新宋体>Student</FONT></CODE> 类对应的和与 <CODE><FONT face=新宋体>Professor</FONT></CODE> 类对应的数据实体，因为它们是具体类，但没有与 <CODE><FONT face=新宋体>Person</FONT></CODE> 类对应的数据实体，因为它是抽象类（它的名称以斜体字表示）。为每个数据实体都分别分配了自己的主键， <CODE><FONT face=新宋体>studentOID</FONT></CODE> 和 <CODE><FONT face=新宋体>professorOID</FONT></CODE>。</P>
<P><A id=art1 name=art1><STRONG>图 3. 将每个具体类映射成单个数据实体</STRONG><BR><IMG alt="图 3. 将每个具体类映射成单个数据实体" border=0 height=107 src="http://bbs.softat.org/ArticleImages/20031212194839453.jpg" width=466 valign="top"></A></P>
<P>这种方法最大的好处是，它仍然能相当容易地执行专门报告，只要您所需的有关单一类的所有数据都只存储在一张表中。但也有几个缺点。一个是当修改类时，必须修改它的表和它所有子类的表。例如，如果要向 <CODE><FONT face=新宋体>Person</FONT></CODE> 类添加高度和重量，就需要同时更新两个表，它会涉及很多工作。第二，无论何时，只要对象更改了它的角色 - 可能您聘用了您一个刚毕业的学生作为教授 - 则需要将数据复制到相应的表中，并为它指定一个新的 OID。这又涉及到很多工作。第三，很难在支持多个角色的同时仍维护数据完整性。（这种情况是可能的；只是比原先困难一点。）例如，您会在哪里存储既是学生又是教授的人的姓名呢？</P><A id=2 name=2></A>
<P><B>每个类使用一个数据实体</B><BR>使用这种方法，为每个类创建一张表，它的属性是 OID 和特定于该类的属性。图 4 描述了采取这个方法时图 1 的类层次结构的持久模型。 请注意，将 <CODE><FONT face=新宋体>personOID</FONT></CODE> 用作了所有三个数据实体的主键。图 4 的一个有趣的特性是，为 <CODE><FONT face=新宋体>Professor</FONT></CODE> 和 <CODE><FONT face=新宋体>Student</FONT></CODE> 中的 <CODE><FONT face=新宋体>personOID</FONT></CODE> 列都分配了两个构造型，而这在标准建模语言 (UML) 中是不允许的。我的意见是，这是一个必须由 UML 持久性建模概要解决的问题，甚至可能在这个建模规则中也需要更改。（有关持久性模型的详细信息，请参阅<A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#resources">参考资料</A>中的 "Towards a UML Profile for a Relational Persistence Model"。）</P>
<P><A id=art1 name=art1><STRONG>图 4. 将每个类映射成它自己的数据实体</STRONG><BR><IMG alt="" border=0 height=227 src="http://bbs.softat.org/ArticleImages/20031212194840256.jpg" width=578 pop="图 4. 将每个类映射成它自己的数据实体" valign="top"></A></P>
<P>这种方法的最大好处就是它能够最好地适应面向对象的概念。它能够很好地支持多态性，对于对象可能有的每个角色，只需要在相应的表中保存记录。修改超类和添加新的子类也非常容易，因为您只需要修改或添加一张表。这种方法也有几个缺点。第一，数据库中有大量的表 -- 实际上每类都有一个（加上维护关系的表）。第二，使用这种技术读取和写入数据的时间比较长，因为您必须访问多个表。如果通过将类层次结构中的每个表放入不同物理磁盘驱动器盘片（假设每个磁盘驱动器磁头都单独操作）上来智能地组织数据库的话，就可以缓解这个问题。第三，有关数据库的专门报告很困难，除非添加一些视图来模拟所需的表。</P><A id=3 name=3></A>
<P><STRONG class=subhead>比较映射策略</STRONG><BR>现在，请注意，每个映射策略怎样产生不同的模型。要理解三种策略之间的设计优缺点，请考虑图 5 中显示的对我们的类层次结构做些简单的更改：添加了 <CODE><FONT face=新宋体>TenuredProfessor</FONT></CODE>，这是从 <CODE><FONT face=新宋体>Professor</FONT></CODE> 中继承的。</P>
<P><A id=art1 name=art1><STRONG>图 5. 扩展初始类层次结构</STRONG><BR><IMG alt="" border=0 height=275 src="http://bbs.softat.org/ArticleImages/20031212194840735.jpg" width=392 pop="图 5. 扩展初始类层次结构" valign="top"></A></P>
<P>图 6 显示了一个更新过的持久性模型，用于将整个类层次结构映射成一个数据实体。尽管很明显，数据库中的空间浪费增加了，但请注意，按照这种策略操作，只需花非常小的代价就可以更新模型。</P>
<P><A id=art1 name=art1><STRONG>图 6. 将扩展的层次结构映射成单一数据实体</STRONG><BR><IMG alt="图 6. 将扩展的层次结构映射成单一数据实体" border=0 height=158 src="http://bbs.softat.org/ArticleImages/20031212194840463.jpg" width=218 valign="top"></A></P>
<P>图 7 显示了将每个具体类映射成数据实体时的持久性模型。使用这个策略，虽然因为我们从教授提升到终身教授，这样对象和我们的关系就有了改变（学生变成教授），所以如何处理对象的这个问题更复杂了，但我只需要添加一个新表。</P>
<P><A id=art1 name=art1><STRONG>图 7. 将扩展的层次结构的具体类映射成数据实体</STRONG><BR><IMG alt="" border=0 height=245 src="http://bbs.softat.org/ArticleImages/20031212194840140.jpg" width=466 pop="图 7. 将扩展的层次结构的具体类映射成数据实体" valign="top"></A></P>
<P>图 8 显示了第三种映射策略的解决方案 -- 将单个类映射成单个数据实体。这需要我添加一个只包括 <CODE><FONT face=新宋体>TenuredProfessor</FONT></CODE> 类的新属性的新表。这种方法的缺点是，要使用新类的实例，它需要好几个数据库访问。</P>
<P><A id=art1 name=art1><STRONG>图 8. 将扩展的层次结构的所有类映射成数据实体</STRONG><BR><IMG alt="" border=0 height=359 src="http://bbs.softat.org/ArticleImages/20031212194840119.jpg" width=576 pop="图 8. 将扩展的层次结构的所有类映射成数据实体" valign="top"></A></P><!-- <p><img SRC="mappingFig08.jpg" height=359 width=674 alt=""> -->
<P>要摒弃这样一种观点，即这些办法都不够好；每种办法都有其优缺点。在下面的表 1 中对它们进行比较。</P>
<P><B>表 1. 比较映射继承的各种办法</B></P>
<TABLE border=1 borderColor=#000000 cellPadding=7 width=590>
<TBODY>
<TR>
<TD bgColor=#ffffff vAlign=top width="28%">
<CENTER><B>考虑因素</B></CENTER></TD>
<TD bgColor=#ffffff vAlign=top width="24%">
<CENTER><B>每个层次结构一张表</B></CENTER></TD>
<TD bgColor=#ffffff vAlign=top width="24%">
<CENTER><B>每个具体类一张表</B></CENTER></TD>
<TD bgColor=#ffffff vAlign=top width="24%">
<CENTER><B>每个类一张表</B></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>专门报告</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>容易</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等/困难</FONT></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>实现的难易程度</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>容易</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>困难</FONT></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>数据访问的难易程度</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>容易</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>容易</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等/容易</FONT></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>耦合</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>非常高</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>高</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>低</FONT></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>数据访问速度</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>快</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>快</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等/快</FONT></CENTER></TD></TR>
<TR>
<TD vAlign=top width="28%"><FONT size=-1>对多态性的支持</FONT></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>中等</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>低</FONT></CENTER></TD>
<TD vAlign=top width="24%">
<CENTER><FONT size=-1>高</FONT></CENTER></TD></TR></TBODY></TABLE><A id=4 name=4></A>
<P><STRONG class=subhead>映射关联、聚合和组成</STRONG><BR>不仅必须将对象映射到数据库中，还必须将对象之间的关系进行映射，这样才能在以后进行恢复。对象之间有四种类型的关系：继承、关联、聚合和组成。要有效地映射这些关系，必须理解它们之间的差异、如何实现一般的关系，以及如何实现特定的多对多关系。</P><A id=5 name=5></A>
<P><STRONG class=subhead>关联、聚合和组合之间的差异</STRONG><BR>从数据库的角度看，关联和聚合／组合关系之间的唯一不同是对象相互之间的绑定程度。对于聚合和组合，在数据库中对整体所做的操作通常需要同时对部分进行操作，而关联就不是这样。</P>
<P>在图 9 中有三个类，其中两个在它们之间有简单的关联关系，有两个共享聚合关系（实际上，组合可能是这种模型中更确切的说法）。（有关关系的详细信息，请参阅<A href="http://www-900.ibm.com/developerWorks/cn/components/mapping-to-rdb/index.shtml#resources">参考资料</A>中的 "Building Object Applications That Work"。）从数据库的观点看，聚合／组合和关联是不同的，在聚合情况下，在整体中读取时，您通常希望在部分中读取，而在关联情况下，需要执行什么操作并不总是那么明显。在将对象保存到数据库中或从数据库中删除对象也存在相同的情况。当然，上述讨论通常特定于商业领域，但这种经验之谈往往在很多情况下出现。</P>
<P><A id=art1 name=art1><STRONG>图 9. 关联和聚合／组合之间的差异</STRONG><BR><IMG alt="图 9. 关联和聚合／组合之间的差异" border=0 height=99 src="http://bbs.softat.org/ArticleImages/20031212194841165.jpg" width=538 valign="top"></A></P><A id=6 name=6></A>
<P><STRONG class=subhead>在关系数据库中实现关系</STRONG><BR>关系数据库中的关系是通过使用外键来维护的。外键是在一张表中出现的一个或多个数据属性；它可以是另一张表的键的一部分，或者干脆碰巧就是另一张表的键。外键可以让您将一张表中的一行与另一张表中的一行相关起来。要实现一对一和一对多的关系，您只需要将一张表的键包括在另一张表中。</P>
<P>在图 10 中有三张表，它们的键 (OID) 和外键用于在它们之间实现关系。首先，在 <CODE><FONT face=新宋体>Position</FONT></CODE> 和 <CODE><FONT face=新宋体>Employee</FONT></CODE> 数据实体间有一个一对一的关联。一对一关联就是它的每个复合度的最大值都是 1 的这么一种关系。要实现这个关系，我在 <CODE><FONT face=新宋体>Employee</FONT></CODE> 数据实体中使用属性 <CODE><FONT face=新宋体>positionOID</FONT></CODE>，<CODE><FONT face=新宋体>Position</FONT></CODE> 数据实体的键。因为关联是单向的 -- employee 那些行知道它们的位置行，但反过来就不行 -- 所以我必须这么做。如果这是个双向的关联，我还会在 <CODE><FONT face=新宋体>Position</FONT></CODE> 中添加一个名为 <CODE><FONT face=新宋体>employeeOID</FONT></CODE> 的外键。然后，使用相同的方法在 <CODE><FONT face=新宋体>Employee</FONT></CODE> 和 <CODE><FONT face=新宋体>Task</FONT></CODE> 之间实现了多对一关联（又称为一对多关联），唯一的不同是将外键放在了 <CODE><FONT face=新宋体>Task</FONT></CODE> 中，因为它在关系的“多”方。</P>
<P><A id=art1 name=art1><STRONG>图 10. 简单人力资源数据库的持久性模型。</STRONG><BR><IMG alt="" border=0 height=589 src="http://bbs.softat.org/ArticleImages/20031212194841806.jpg" width=579 pop="图 10. 简单人力资源数据库的持久性模型" valign="top"></A></P><A id=7 name=7></A>
<P><STRONG class=subhead>实现多对多关联</STRONG><BR>要实现多对多关系，需要关联表的概念，它是一种数据实体，唯一目标是在关系数据库中维护两个或多个表之间的关联。图 10 中，在<CODE><FONT face=新宋体>Employee</FONT></CODE> 和 <CODE><FONT face=新宋体>Benefit</FONT></CODE> 之间有一个多对多关系。图 11 中，可以看到如何使用关联表来实现多对多关系。在关系数据库中，关联表中包含的属性传统上是关系中涉及到的表中的键组合。关联表的名称通常是它所关联的表的名称组合，或者是它实现的关联的名称。在这种情况下，我选择 <CODE><FONT face=新宋体>EmployeeBenefit</FONT></CODE> 而不是 <CODE><FONT face=新宋体>BenefitEmployee</FONT></CODE> 和 <CODE><FONT face=新宋体>has</FONT></CODE>，因为我觉得它可以更好地反映关联的性质。</P>
<P><A id=art1 name=art1><STRONG>图 11. 在关系数据库中实现多对多关系</STRONG><BR><IMG alt="" border=0 height=159 src="http://bbs.softat.org/ArticleImages/20031212194842451.jpg" width=580 pop="图 11. 在关系数据库中实现多对多关系" valign="top"></A></P>
<P>看一下图 11 中应用程序的复合度。规则是，一旦引入了关联表，复合度就“交叉”，如图 12 所示。值为 '1' 的复合度总在外边缘引入，如图 11 和 12 中所示，以保留原始关联的整体复合度。原始的关联表明雇员有一种或多种福利，并且任何给定的福利都给予一个或多个雇员。在图 11 中您可以看到，即使在有关联表维护关联的情况下仍然是这种情况。</P>
<P><A id=art1 name=art1><STRONG>图 12. 关联表简介</STRONG><BR><IMG alt="" border=0 height=219 src="http://bbs.softat.org/ArticleImages/20031212194842636.jpg" width=472 pop="图 12. 关联表简介" valign="top"></A></P>
<P>有必要注明我选择应用构造型“&lt;&lt;关联表&gt;&gt;”而不是关联类的说明 -- 将关联类与它所描述的关联连接的虚线行 -- 出于两个原因。首先，关联表的目的是实现关联，而关联类的目的是描述关联。其次，图 11 中采取的方法反映了为使用关系技术所需的实际实现策略。</P><A id=8 name=8></A>
<P><STRONG class=subhead>结束</STRONG></P></SPAN><img src ="http://www.blogjava.net/jelver/aggbug/35292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-14 20:41 <a href="http://www.blogjava.net/jelver/articles/35292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用rational rose 2003 设计商业销售系统</title><link>http://www.blogjava.net/jelver/articles/34947.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 12 Mar 2006 16:10:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/34947.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/34947.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/34947.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/34947.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/34947.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本次分析设计是针对一个商业销售系统中的几个主要业务进行建模。我们的设计对象是一个商场的商业销售系统。商场下设有业务部、仓库、若干柜台组及收银台等，业务部负责组织进货、保管及销售，仓库对购进的商品进行保管，而柜台则是进行商品零售的场所，收银台作为大厦财务出纳的收款点负责零售商品的收款。1. 现有系统描述该商场现有部门如下：家用电器经理部、家用电器大件柜、家用电器小件柜；五金交电经...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/34947.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/34947.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-13 00:10 <a href="http://www.blogjava.net/jelver/articles/34947.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ERwin相关概念快速入门(albertyi原创)</title><link>http://www.blogjava.net/jelver/articles/34454.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 09 Mar 2006 05:14:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/34454.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/34454.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/34454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/34454.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/34454.html</trackback:ping><description><![CDATA[ERwin相关概念快速入门(albertyi原创)<BR><BR>1、如果只做文档，可以选择只建立logical view2、如果是做项目，需要同时使用Logical view 和physical view3、一般Logical view是用于做文档的，而physical view是用于生成或者导出脚本的4、表之间的三种连接线，第一种用于把表1中的主键插入到表2中的外键，且插入的作为表2的主键第二种用于多对多，很少用到第一种用于把表1中的主键插入到表2中的外键，且插入的不作为表2的主键<BR><BR>5、Logical中的和physical中对应的表的名称可以不一样，一般在physical中的表的名称用英文名称在Logical中的表的名称则无所谓，如果需要可以用中文<BR><BR>6、在Physical view中的Tools中的[Forward Engineer/Schema Generation]中在右侧的表中用对勾可以选择需要操作的项目<BR><BR>点击【preview】可以看到脚本，可以复制过来改改就能是脚本了点击【report】可以直接导出脚本点击【Generate】则可以直接连接到数据库，把相关的Scheme都建立起来<BR><BR>7、在Logical view的一个Entity上右键点击，选择attributes，就进入了给表加入column的界面了在General中选择一种基本类型(Domain)比如string后，就能加入一个名称了，Attribute name就是Logical view中的名字Column name就是用于生成脚本的名称。在General中的Primary Key的checkbox就是选为主键的地方了。在DataType中就能设定具体的数据类型，比如VARCHAR2,NUMBER等。<BR><BR>8、关于索引和约束的建立右键在Entity上，选择Key Group就能新建约束了<BR><BR>9、在Attribute中选择Datatype就能在Validate中选择这个column相关的约束，在Default中选择这个column的默认值了<BR><BR>10、关于Domains的概念Domain的概念在Sql server中是支持的，可以在脚本的最开始就定义一堆的Domain,然后在其后的脚本中都引用相关的域名，而不用直接原始的数据类型了。<BR><BR>for example：在一个项目的数据库设计中卡号用得非常的多：所以在ERwin中Logical view中选择Domain,然后右键点击? &lt;unkonwn&gt;，new，就能创建一种新的Domain在叫做Cardseries。选择property可以给他选择相关的属性，比如选择Datatype为VARCHAR(18)，还可以给它选择约束等等。<BR><BR>这个新建的Domain 就能在这个项目中方便的使用了。<BR><BR>11、关于Subject Area的概念当整个项目设计表比较多的时候，很难在一个view中连接清楚所有的表的之间的关系这样就需要在Subject Area中分多个Area，把相关的表放到相关的的Area中去连接关系，这样比较方便设计。<BR><BR>1&gt;右键点在一个相应的Area上，然后go to ，就能看到那个Area相应的View2&gt;右键－&gt;property,就能设置当前Area中需要哪些表,其中比较有用的一组按钮是最后一组(两个)，能把选中的要加入Area的表的相关的M级Ancester和N级Descendant同时加入Area，至于M和N可以自己选择，非常方便。<BR><BR>注意：在任何非主Area中新建的Entity都会在&lt;Main Subject Area&gt;中有一份，删除也是同时进行的<img src ="http://www.blogjava.net/jelver/aggbug/34454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-09 13:14 <a href="http://www.blogjava.net/jelver/articles/34454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高级 DAO 编程</title><link>http://www.blogjava.net/jelver/articles/32010.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Wed, 22 Feb 2006 12:29:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32010.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32010.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32010.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32010.html</trackback:ping><description><![CDATA[<!-- END HEADER AREA--><!-- START BODY AREA-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD width=10><FONT size=2><IMG alt="" border=0 height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=10></FONT></TD>
<TD width="100%">
<TABLE align=right border=0 cellPadding=0 cellSpacing=0 width=168>
<TBODY>
<TR><!-- Sidebar Gutter-->
<TD width=8><FONT size=2><IMG alt="" height=21 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=5></FONT></TD>
<TD width=160><!-- Start TOC-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width=160>
<TBODY>
<TR>
<TD bgColor=#000000 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=middle background="" height=5><FONT size=2><B>内容：</B> </FONT></TD></TR>
<TR>
<TD bgColor=#666666 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=right>
<TABLE border=0 cellPadding=3 cellSpacing=0 width="98%">
<TBODY>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAHCMIB"><FONT size=2>DAO 基础</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDA0CMIB"><FONT size=2>事务界定</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDADFMIB"><FONT size=2>使用 JDBC 进行事务界定</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAVGMIB"><FONT size=2>JTA 概述</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDA2HMIB"><FONT size=2>使用 JTA 的事务界定</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAQRMIB"><FONT size=2>用于事务控制的 JTA 方法</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAITMIB"><FONT size=2>使用 JTA 和 JDBC</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDALVMIB"><FONT size=2>选择最好的方式</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAAWMIB"><FONT size=2>日志记录和 DAO</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAZYMIB"><FONT size=2>DAO 中的异常处理</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDAY0MIB"><FONT size=2>实现实例：MovieDAO</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#IDATANIB"><FONT size=2>结束语</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#resources"><FONT size=2>参考资料</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#author1"><FONT size=2>关于作者</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#rating"><FONT size=2>对本文的评价</FONT></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- End TOC--><!-- Start Related Content Area-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width=160>
<TBODY>
<TR>
<TD bgColor=#000000 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=middle background="" height=5><FONT size=2><B>相关内容：</B> </FONT></TD></TR>
<TR>
<TD bgColor=#666666 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=right>
<TABLE border=0 cellPadding=3 cellSpacing=0 width="98%">
<TBODY>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/java/j-sdao/"><FONT size=2>使用 SDAO 进行 J2EE 测试的分步方法</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-106.ibm.com/developerworks/ibm/edu/i-dw-i-2extreme6-i.html" xmlns=""><FONT size=2>Create persistent application data with Java Data Objects</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-106.ibm.com/developerworks/java/library/j-jtp0305.html" xmlns=""><FONT size=2>理解 JTS -- 事务处理简介</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-106.ibm.com/developerworks/toolbox/"><FONT size=2>developerWorks Toolbox subscription</FONT></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- End TOC--><!-- Start Related Content Area-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width=160>
<TBODY>
<TR>
<TD bgColor=#000000 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=middle background="" height=5><A class=nav href="http://www-900.ibm.com/developerWorks/cn/java/index.shtml"><B><FONT size=2>Java 专区中还有:</FONT></B></A></TD></TR>
<TR>
<TD bgColor=#666666 height=1 width=160><FONT size=2><IMG alt="" height=1 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD align=right>
<TABLE border=0 cellPadding=3 cellSpacing=0 width="98%">
<TBODY>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/cnedu.nsf/java-onlinecourse-bytitle?OpenView&amp;Count=500"><FONT size=2>教学</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/cntools.nsf/dw/java-all-byname?OpenDocument&amp;count=500"><FONT size=2>工具与产品</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/cntools.nsf/dw/java-beans-bytitle?OpenDocument&amp;count=500"><FONT size=2>代码与组件</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/cnpapers.nsf/java-papers-bynewest?OpenView&amp;Count=500"><FONT size=2>所有文章</FONT></A></TD></TR>
<TR>
<TD><A href="http://www-900.ibm.com/developerWorks/cn/cntips.nsf/java-tips-bydate?OpenView&amp;Count=500"><FONT size=2>实用技巧</FONT></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- End Related dW Content Area-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width=160>
<TBODY>
<TR>
<TD bgColor=#000000 colSpan=2 height=2 width=150><FONT size=2><IMG alt="" height=2 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR>
<TR>
<TD bgColor=#ffffff colSpan=2 height=2 width=150><FONT size=2><IMG alt="" height=2 src="http://www-900.ibm.com/developerWorks/cn/i/c.gif" width=160></FONT></TD></TR></TBODY></TABLE><!-- END STANDARD SIDEBAR AREA--></TD></TR></TBODY></TABLE><FONT size=2><SPAN class=atitle2>1.2学习编译更好的 DAO 的技巧</SPAN> <BR></FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#author1"><FONT size=2>Sean C. Sullivan</FONT></A><FONT size=2> (</FONT><A href="mailto:dao-article@seansullivan.com"><FONT size=2>dao-article@seansullivan.com</FONT></A><FONT size=2>)<BR></FONT>
<BLOCKQUOTE><FONT size=2>J2EE 开发人员使用数据访问对象(Data Access Object DAO)设计模式，以便将低级别的数据访问逻辑与高级别的业务逻辑分离。实现 DAO 模式涉及比编写数据访问代码更多的内容。在本文中，Java 开发人员 Sean C. Sullivan 讨论了 DAO 编程中三个常常被忽略的方面：事务界定、异常处理和日志记录。</FONT></BLOCKQUOTE>
<P><FONT size=2>在过去 18 个月中，我参加了一个由有才华的软件工程师组成的小组，构建定制的、基于 Web 的供应链管理应用程序。我们的应用程序访问范围广泛的持久性数据，包括配送状态、供应链衡量(metrics)、库存、货运发票、项目管理数据和用户信息。我们用 JDBC API 连接到我们公司的不同数据库平台上，并在整个应用程序中使用 DAO 设计模式。</FONT></P>
<P><FONT size=2>图 1 显示了应用程序和数据源之间的关系：</FONT></P>
<P><A name=IDAYBMIB><B><FONT size=2>图 1. 应用程序和数据源</FONT></B></A><BR><FONT size=2><IMG alt=应用程序和数据源 height=176 src="http://www-900.ibm.com/developerworks/cn/java/j-dao/images/jwebapps.jpg" width=282></FONT></P>
<P><FONT size=2>在整个应用程序中使用数据访问对象(DAO)使我们可以将底层数据访问逻辑与业务逻辑分离开来。我们构建了为每一个数据源提供 GRUD (创建、读取、更新、删除)操作的 DAO 类。</FONT></P>
<P><FONT size=2>在本文中，我将为您介绍构建更好的 DAO 类的 DAO 实现策略和技术。更确切地说，我将讨论日志、异常处理和事务界定。您将学到如何将这三者结合到自己的 DAO 类中。本文假定您熟悉 JDBC API、SQL 和关系数据库编程。</FONT></P>
<P><FONT size=2>我们将以对 DAO 设计模式和数据访问对象的概述开始。</FONT></P>
<P><A name=IDAHCMIB><SPAN class=atitle2><FONT size=2>DAO 基础</FONT></SPAN></A><BR><FONT size=2>DAO 模式是标准 J2EE 设计模式之一。开发人员用这种模式将底层数据访问操作与高层业务逻辑分离开。一个典型的 DAO 实现有以下组件：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>一个 DAO 工厂类 </FONT>
<LI><FONT size=2>一个 DAO 接口 </FONT>
<LI><FONT size=2>一个实现了 DAO 接口的具体类 </FONT>
<LI><FONT size=2>数据传输对象(有时称为值对象) </FONT></LI></UL>
<P><FONT size=2>具体的 DAO 类包含访问特定数据源的数据的逻辑。在下面一节中您将学习设计和实现数据访问对象的技术。有关 DAO 设计模式的更多内容请参阅</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#resources" xmlns=""><FONT size=2> 参考资料</FONT></A><FONT size=2>。</FONT></P>
<P><A name=IDA0CMIB><SPAN class=atitle2><FONT size=2>事务界定</FONT></SPAN></A><BR><FONT size=2>关于 DAO 要记住的重要一点是它们是事务性对象。由 DAO 所执行的每一个操作 -- 如创建、更新或者删除数据 -- 都与一个事务相关联。因此，<I xmlns="">事务界定</I>的概念就变得特别重要了。</FONT></P>
<P><FONT size=2>事务界定是定义事务边界的方式。J2EE 规范描述了两种事务界定的模型：编程式(programmatic)和声明式(declarative)。表 1 分析了这两种模型：</FONT></P>
<P><FONT size=2><B xmlns="">表 1. 两种事务界定的模型</B> </FONT>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><B xmlns=""><FONT size=2>声明式事务界定</FONT></B></TD>
<TD><B xmlns=""><FONT size=2>编程式事务界定</FONT></B></TD></TR>
<TR>
<TD><FONT size=2>程序员用 EJB 部署描述符声明事务属性。</FONT></TD>
<TD><FONT size=2>程序员负责编写事务逻辑。</FONT></TD></TR>
<TR>
<TD><FONT size=2>运行时环境(EJB 容器)用这些属性自动管理事务。</FONT></TD>
<TD><FONT size=2>应用程序通过一个 API 控制事务。</FONT></TD></TR></TBODY></TABLE></P>
<P><FONT size=2>我们将侧重于编程式事务界定。</FONT></P>
<P><A name=IDAZDMIB><SPAN class=atitle3><FONT size=2>设计考虑</FONT></SPAN></A><BR><FONT size=2>如前所述，DAO 是事务性对象。一个典型的 DAO 执行像创建、更新和删除这样的事务性操作。在设计 DAO 时，首先要问自己以下问题：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>事务要如何开始？ </FONT>
<LI><FONT size=2>事务应如何结束？ </FONT>
<LI><FONT size=2>哪一个对象将负责开始一个事务？ </FONT>
<LI><FONT size=2>哪一个对象将负责结束一个事务？ </FONT>
<LI><FONT size=2>DAO 是否要负责事务的开始和结束？ </FONT>
<LI><FONT size=2>应用程序是否需要通过多个 DAO 访问数据？ </FONT>
<LI><FONT size=2>事务涉及到一个 DAO 还是多个 DAO？ </FONT>
<LI><FONT size=2>一个 DAO 是否调用另一个 DAO 的方法？ </FONT></LI></UL>
<P><FONT size=2>了解上述问题的答案将有助于您选择最适合的 DAO 的事务界定策略。在 DAO 中有两种主要的界定事务的策略。一种方式是让 DAO 负责界定事务，另一种将事务界定交给调用这个 DAO 方法的对象处理。如果选择了前一种方式，那么就将事务代码嵌入到 DAO 中。如果选择后一种方式，那么事务界定代码就是在 DAO 类外面。我们将使用简单的代码示例帮助您更好理解每一种方式是如何工作的。</FONT></P>
<P><FONT size=2>清单 1 显示了一个有两种数据操作的 DAO：创建和更新：</FONT></P><A name=IDAMEMIB><B><FONT size=2>清单 1. DAO 方法</FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> public void createWarehouseProfile(WHProfile profile); public void updateWarehouseStatus(WHIdentifier id, StatusInfo status); </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>清单 2 显示了一个简单的事务。事务界定在 DAO 类外面。注意在这个例子中调用者是如何在一个事务中结合多个 DAO 操作的。</FONT></P><A name=IDAXEMIB><B><FONT size=2>清单 2. 调用者管理的事务</FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> tx.begin(); // start the transaction dao.createWarehouseProfile(profile); dao.updateWarehouseStatus(id1, status1); dao.updateWarehouseStatus(id2, status2); tx.commit(); // end the transaction </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>这种事务界定策略对于需要在一个事务中访问多个 DAO 的应用程序特别有用。</FONT></P>
<P><FONT size=2>可以用 JDBC API 或者 Java 事务 API(Java Transaction API JTA)实现事务界定。 JDBC 事务界定比 JTA 事务界定要简单，但是 JTA 提供了更多的灵活性。在下面一节中我将更深入地分析事务界定的机制。</FONT></P>
<P><A name=IDADFMIB><SPAN class=atitle2><FONT size=2>用 JDBC 进行事务界定</FONT></SPAN></A><BR><FONT size=2>JDBC 事务是用<CODE> Connection</CODE> 对象控制的。JDBC Connection 接口(<CODE>java.sql.Connection</CODE>)提供了两种事务模式：自动提交和手工提交。<CODE>java.sql.Connection</CODE> 提供了以下控制事务的方法：</FONT></P>
<UL xmlns="">
<LI><FONT size=2><CODE>public void setAutoCommit(boolean)</CODE> </FONT>
<LI><FONT size=2><CODE>public boolean getAutoCommit()</CODE> </FONT>
<LI><FONT size=2><CODE>public void commit()</CODE> </FONT>
<LI><CODE><FONT size=2>public void rollback()</FONT></CODE></LI></UL>
<P><FONT size=2>清单 3 显示了如何用 JDBC API 界定一个事务：</FONT></P><A name=IDAKGMIB><B><FONT size=2>清单 3. 用 JDBC API 进行事务界定</FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> import java.sql.*; import javax.sql.*; // ... DataSource ds = obtainDataSource(); Connection conn = ds.getConnection(); conn.setAutoCommit(false); // ... pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "The Great Escape"); pstmt.executeUpdate(); // ... conn.commit(); // ... </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>使用 JDBC 事务界定时，您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。在下面，我们将看一下如何用 JTA 进行事务界定。因为 JTA 不像 JDBC 那样有名，所以我们首先做一个简介。</FONT></P>
<P><A name=IDAVGMIB><SPAN class=atitle2><FONT size=2>JTA 简介</FONT></SPAN></A><BR><FONT size=2>Java 事务 API(JTA) 及其同门兄弟 Java 事务服务(Java Transaction Service JTS)为 J2EE 平台提供了分布式事务服务。一个<I xmlns="">分布式的事务</I>涉及一个事务管理器和一个或者多个资源管理器。一个<I xmlns="">资源管理器</I>是任何类型的持久性的数据存储。事务管理器负责协调所有事务参与者之间的通信。事务管理器与资源管理器之间的关系如图 2 所示：</FONT></P>
<P><A name=IDADHMIB><B><FONT size=2>图 2. 一个事务管理器和资源管理器</FONT></B></A><BR><FONT size=2><IMG alt=一个事务管理器和资源管理器 height=244 src="http://www-900.ibm.com/developerworks/cn/java/j-dao/images/transactionmanager.jpg" width=358></FONT></P>
<P><FONT size=2>JTA 事务比 JDBC 事务功能更强。JDBC 事务局限为一个数据库连接，而 JTA 事务可以有多个参与者。所有下列 Java 平台组件都可以参与 JTA 事务：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>JDBC 连接 </FONT>
<LI><FONT size=2>JDO <CODE>PersistenceManager</CODE> 对象 </FONT>
<LI><FONT size=2>JMS 队列 </FONT>
<LI><FONT size=2>JMS 主题 </FONT>
<LI><FONT size=2>企业 JavaBeans </FONT>
<LI><FONT size=2>符合 J2EE 连接体系结构(J2EE Connector Architecture)规范的资源适配器 </FONT></LI></UL>
<P><A name=IDA2HMIB><SPAN class=atitle2><FONT size=2>使用 JTA 的事务界定</FONT></SPAN></A><BR><FONT size=2>要用 JTA 进行事务界定，应用程序要调用 <CODE>javax.transaction.UserTransaction</CODE> 接口中的方法。清单 4 显示了对 <CODE>UserTransaction</CODE> 对象的典型 JNDI 查询：</FONT></P><A name=IDAQQMIB><B><FONT size=2>清单 4. 一个对 UserTransaction 对象的</FONT></B></A><FONT size=2><STRONG> JDNI 查询</STRONG><BR></FONT>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> import javax.transaction.*; import javax.naming.*; // ... InitialContext ctx = new InitialContext(); Object txObj = ctx.lookup("java:comp/UserTransaction"); UserTransaction utx = (UserTransaction) txObj; </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>当应用程序找到了 <CODE>UserTransaction </CODE>对象后，就可以开始事务了，如清单 5 所示：</FONT></P><A name=IDAARMIB><B><FONT size=2>清单 5. 用 JTA 开始一个事务</FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> utx.begin(); // ... DataSource ds = obtainXADataSource(); Connection conn = ds.getConnection(); pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "Spinal Tap"); pstmt.executeUpdate(); // ... utx.commit(); // ... </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>当应用程序调用<CODE> commit()</CODE>时，事务管理器用一个两阶段的提交协议结束事务。</FONT></P>
<P><A name=IDAQRMIB><SPAN class=atitle3><FONT size=2>控制事务的 JTA 方法</FONT></SPAN></A><BR><FONT size=2><CODE>javax.transaction.UserTransaction</CODE> 接口提供了以下事务控制方法：</FONT></P>
<UL xmlns="">
<LI><FONT size=2><CODE>public void begin()</CODE> </FONT>
<LI><FONT size=2><CODE>public void commit()</CODE> </FONT>
<LI><FONT size=2><CODE>public void rollback()</CODE> </FONT>
<LI><FONT size=2><CODE>public int getStatus()</CODE> </FONT>
<LI><FONT size=2><CODE>public void setRollbackOnly()</CODE> </FONT>
<LI><CODE><FONT size=2>public void setTransactionTimeout(int)</FONT></CODE></LI></UL>
<P><FONT size=2>应用程序调用<CODE> begin()</CODE> 开始事务。应用程序调用 <CODE>commit()</CODE> 或者<CODE> rollback()</CODE> 结束事务。参阅</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#resources" xmlns=""><FONT size=2>参考资料</FONT></A><FONT size=2>以了解更多关于用 JTA 进行事务管理的内容。</FONT></P>
<P><A name=IDAITMIB><SPAN class=atitle2><FONT size=2>使用 JTA 和 JDBC</FONT></SPAN></A><BR><FONT size=2>开发人员通常在 DAO 类中用 JDBC 进行底层数据操作。如果计划用 JTA 界定事务，那么就需要有一个实现 <CODE>javax.sql.XADataSource</CODE>、<CODE>javax.sql.<A name=0></A><B style="BACKGROUND-COLOR: #ffff66; COLOR: black">XAConnection</B> </CODE>和 <CODE>javax.sql.XAResource</CODE> 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个<CODE> XADataSource</CODE> 对象就是一个 <CODE><B style="BACKGROUND-COLOR: #ffff66; COLOR: black">XAConnection</B></CODE> 对象的工厂。<CODE><B style="BACKGROUND-COLOR: #ffff66; COLOR: black">XAConnection</B></CODE>s 是参与 JTA 事务的 JDBC 连接。</FONT></P>
<P><FONT size=2>您将需要用应用服务器的管理工具设置<CODE> XADataSource</CODE>。从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。</FONT></P>
<P><FONT size=2>J2EE 应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象，它就调用<CODE> javax.sql.DataSource.getConnection()</CODE> 以获得到数据库的连接。</FONT></P>
<P><FONT size=2>XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时，应用程序一定不要对 XA 连接调用 <CODE>java.sql.Connection.commit()</CODE> 或者<CODE> java.sql.Connection.rollback()</CODE>。相反，应用程序应该使用<CODE> UserTransaction.begin()、</CODE><CODE>UserTransaction.commit()</CODE> 和<CODE> serTransaction.rollback()</CODE>。</FONT></P>
<P><A name=IDALVMIB><SPAN class=atitle2><FONT size=2>选择最好的方式</FONT></SPAN></A><BR><FONT size=2>我们讨论了如何用 JDBC 和 JTA 界定事务。每一种方式都有其优点，您需要决定哪一种最适合于您的应用程序。</FONT></P>
<P><FONT size=2>在最近的许多项目中，我们小组是用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>事务界定代码嵌入在 DAO 类中。 </FONT>
<LI><FONT size=2>DAO 类使用 JDBC API 进行事务界定。 </FONT>
<LI><FONT size=2>调用者不能界定事务。 </FONT>
<LI><FONT size=2>事务范围局限于单个 JDBC 连接。 </FONT></LI></UL>
<P><FONT size=2>JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库，那么下列实现策略也许更合适：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>事务用 JTA 界定。 </FONT>
<LI><FONT size=2>事务界定代码从 DAO 中分离出来。 </FONT>
<LI><FONT size=2>调用者负责界定事务。 </FONT>
<LI><FONT size=2>DAO 加入一个全局事务。 </FONT></LI></UL>
<P><FONT size=2>JDBC 方式由于其简单性而具有吸引力，JTA　方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。</FONT></P>
<P><A name=IDAAWMIB><SPAN class=atitle2><FONT size=2>日志记录和 DAO</FONT></SPAN></A><BR><FONT size=2>一个良好实现的 DAO 类将使用日志记录来捕捉有关其运行时行为的细节。您可以选择记录异常、配置信息、连接状态、JDBC 驱动程序元数据、或者查询参数。日志对于开发的所有阶段都很有用。我经常在开发时、测试时和生产中分析应用程序日志。</FONT></P>
<P><FONT size=2>在本节，我将展示一个显示如何将 Jakarta Commons Logging 加入到 DAO 中的代码示例。在这之前，让我们回顾一下一些基本知识。</FONT></P>
<P><A name=IDAJWMIB><SPAN class=atitle3><FONT size=2>选择日志库</FONT></SPAN></A><BR><FONT size=2>许多开发人员使用一种原始格式进行日志记录：<CODE>System.out.println</CODE> 和<CODE> System.err.println</CODE>。<CODE>Println</CODE> 语句速度快且使用方便，但是它们没有提供全功能的日志记录系统所具有的功能。表 2 列出了 Java 平台的日志库：</FONT></P>
<P><FONT size=2><B xmlns="">表 2. Java 平台的日志库</B> </FONT>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><B xmlns=""><FONT size=2>日志库</FONT></B></TD>
<TD><B xmlns=""><FONT size=2>开放源代码？</FONT></B></TD>
<TD><B xmlns=""><FONT size=2>URL</FONT></B></TD></TR>
<TR>
<TD><FONT size=2>java.util.logging</FONT></TD>
<TD><FONT size=2>不是</FONT></TD>
<TD><FONT size=2>http://java.sun.com/j2se/</FONT></TD></TR>
<TR>
<TD><FONT size=2>Jakarta Log4j</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>http://jakarta.apache.org/log4j/</FONT></TD></TR>
<TR>
<TD><FONT size=2>Jakarta Commons Logging</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>http://jakarta.apache.org/commons/logging.html</FONT></TD></TR></TBODY></TABLE></P>
<P><FONT size=2><CODE>java.util.logging</CODE> 是 J2SE 1.4 平台上的标准 API。不过，大多数开发人员同意 Jakarta Log4j 提供了更多的功能和更大的灵活性。Log4j 优于 java.util.logging 的一点是它同时支持 J2SE 1.3 和 J2SE 1.4 平台。</FONT></P>
<P><FONT size=2>Jakarta Commons Logging 可以与<CODE> java.util.logging</CODE> 或者 Jakarta Log4j 一同使用。Commons Logging 是一个日志抽象层，它隔离了应用程序与底层日志实现。使用 Commons Logging，您可以通过改变配置文件更换底层日志实现。Commons Logging 在 Jakarta Struts 1.1 和 Jakarta HttpClient 2.0 中使用。</FONT></P>
<P><A name=IDAGYMIB><SPAN class=atitle3><FONT size=2>一个日志记录示例</FONT></SPAN></A><BR><FONT size=2>清单 7 显示了如何在 DAO 类中使用 Jakarta Commons Logging：</FONT></P><A name=IDAOYMIB><B><FONT size=2>清单 7. DAO 类中的 Jakarta Commons Logging </FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2>import org.apache.commons.logging.*; class DocumentDAOImpl implements DocumentDAO { static private final Log log = LogFactory.getLog(DocumentDAOImpl.class); public void deleteDocument(String id) { // ... log.debug("deleting document: " + id); // ... try { // ... data operations ... } catch (SomeException ex) { log.error("Unable to delete document", ex); // ... handle the exception ... } } } </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>日志记录是所有任务关键型应用程序的重要部分。如果在 DAO 中遇到故障，那么日志通常可以提供判断出错位置的最好信息。将日志加入到 DAO 可以保证您有机会进行调试和故障排除。</FONT></P>
<P><A name=IDAZYMIB><SPAN class=atitle2><FONT size=2>DAO 中的异常处理</FONT></SPAN></A><BR><FONT size=2>我们讨论过了事务界定和日志，现在对于如何在数据访问对象上应用它们有了更深入的理解。我们的第三个和最后一个讨论议题是异常处理。遵从几个简单的异常处理指导可以使您的 DAO 更容易使用、更健壮及更易于维护。</FONT></P>
<P><FONT size=2>在实现 DAO 模式时，考虑以下问题：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>DAO 的公共接口中的方法是否抛出检查过的异常？ </FONT>
<LI><FONT size=2>如果是的话，抛出何种检查过的异常？ </FONT>
<LI><FONT size=2>在 DAO 实现类中如何处理异常？ </FONT></LI></UL>
<P><FONT size=2>在使用 DAO 模式的过程中，我们的小组开发了一些处理异常的原则。遵从这些原则可以极大地改进您的 DAO：</FONT></P>
<UL xmlns="">
<LI><FONT size=2>DAO 方法应该抛出有意义的异常。<BR><BR></FONT>
<LI><FONT size=2>DAO 方法不应该抛出 <CODE>java.lang.Exception</CODE>。<CODE>java.lang.Exception</CODE> 太一般化了。它不传递关于底层问题的任何信息。<BR><BR></FONT>
<LI><FONT size=2>DAO 方法不应该抛出<CODE> java.sql.SQLException</CODE>。SQLException 是一个低级别的 JDBC 异常。一个 DAO 应该力争封装 JDBC 而不是将 JDBC 公开给应用程序的其余部分。<BR><BR></FONT>
<LI><FONT size=2>只有在可以合理地预期调用者可以处理异常时，DAO 接口中的方法才应该抛出检查过的异常。如果调用者不能以有意义的方式处理这个异常，那么考虑抛出一个未检查的(运行时)异常。<BR><BR></FONT>
<LI><FONT size=2>如果数据访问代码捕获了一个异常，不要忽略它。忽略捕获的异常的 DAO 是很难进行故障诊断的。<BR><BR></FONT>
<LI><FONT size=2>使用链接的异常将低级别的异常转化为高级别的异常。<BR><BR></FONT>
<LI><FONT size=2>考虑定义标准 DAO 异常类。Spring Framework (参阅</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#Resources"><FONT size=2>参考资料</FONT></A><FONT size=2>)提供了很好的一套预定义的 DAO 异常类。 </FONT></LI></UL>
<P><FONT size=2>有关异常和异常处理技术的更多信息参阅</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#resources" xmlns=""><FONT size=2>参考资料</FONT></A><FONT size=2>。</FONT></P>
<P><A name=IDAY0MIB><SPAN class=atitle2><FONT size=2>实现实例： MovieDAO</FONT></SPAN></A><BR><FONT size=2><CODE>MovieDAO</CODE> 是一个展示本文中讨论的所有技术的 DAO：事务界定、日志和异常处理。您可以在</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#Resources" xmlns=""><FONT size=2>参考资料</FONT></A><FONT size=2>一节中找到<CODE> MovieDAO</CODE> 源代码。代码分为三个包：</FONT></P>
<UL xmlns="">
<LI><FONT size=2><CODE>daoexamples.exception</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie</CODE> </FONT>
<LI><CODE><FONT size=2>daoexamples.moviedemo</FONT></CODE></LI></UL>
<P><FONT size=2>DAO 模式的这个实现包含下面列出的类和接口：</FONT></P>
<UL xmlns="">
<LI><FONT size=2><CODE>daoexamples.movie.MovieDAOFactory</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.MovieDAO</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.MovieDAOImpl</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.MovieDAOImplJTA</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.Movie</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.MovieImpl</CODE> </FONT>
<LI><FONT size=2><CODE>daoexamples.movie.MovieNotFoundException</CODE> </FONT>
<LI><CODE><FONT size=2>daoexamples.movie.MovieUtil</FONT></CODE></LI></UL>
<P><FONT size=2><CODE>MovieDAO</CODE> 接口定义了 DAO 的数据操作。这个接口有五个方法，如下所示：</FONT></P>
<UL xmlns="">
<LI><FONT size=2><CODE>public Movie findMovieById(String id)</CODE> </FONT>
<LI><FONT size=2><CODE>public java.util.Collection findMoviesByYear(String year)</CODE> </FONT>
<LI><FONT size=2><CODE>public void deleteMovie(String id)</CODE> </FONT>
<LI><FONT size=2><CODE>public Movie createMovie(String rating, String year, String, title)</CODE> </FONT>
<LI><CODE><FONT size=2>public void updateMovie(String id, String rating, String year, String title)</FONT></CODE></LI></UL>
<P><FONT size=2><CODE>daoexamples.movie</CODE> 包包含 <CODE>MovieDAO</CODE> 接口的两个实现。每一个实现使用一种不同的方式进行事务界定，如表 3 所示：</FONT></P>
<P><FONT size=2><B xmlns="">表 3. MovieDAO 实现</B> </FONT>
<TABLE border=1 cellPadding=3 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><FONT size=2></FONT></TD>
<TD><B xmlns=""><FONT size=2>MovieDAOImpl</FONT></B></TD>
<TD><B xmlns=""><FONT size=2>MovieDAOImplJTA</FONT></B></TD></TR>
<TR>
<TD><FONT size=2>实现 MovieDAO 接口?</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>是</FONT></TD></TR>
<TR>
<TD><FONT size=2>通过 JNDI 获得 DataSource？</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>是</FONT></TD></TR>
<TR>
<TD><FONT size=2>从 DataSource 获得 java.sql.Connection 对象？</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>是</FONT></TD></TR>
<TR>
<TD><FONT size=2>DAO 在内部界定事务？</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>否</FONT></TD></TR>
<TR>
<TD><FONT size=2>使用 JDBC 事务？</FONT></TD>
<TD><FONT size=2>是</FONT></TD>
<TD><FONT size=2>否</FONT></TD></TR>
<TR>
<TD><FONT size=2>使用一个 XA DataSource？</FONT></TD>
<TD><FONT size=2>否</FONT></TD>
<TD><FONT size=2>是</FONT></TD></TR>
<TR>
<TD><FONT size=2>参与 JTA 事务？</FONT></TD>
<TD><FONT size=2>否</FONT></TD>
<TD><FONT size=2>是</FONT></TD></TR></TBODY></TABLE></P>
<P><A name=IDAJ5MIB><SPAN class=atitle3><FONT size=2>MovieDAO 演示应用程序</FONT></SPAN></A><BR><FONT size=2>这个演示应用程序是一个名为 <CODE>daoexamples.moviedemo.DemoServlet</CODE> 的 servlet 类。<CODE>DemoServlet</CODE> 使用这两个 Movie DAO 查询和更新表中的电影数据。</FONT></P>
<P><FONT size=2>这个 servlet 展示了如何将支持 JTA 的 <CODE>MovieDAO</CODE> 和 Java 消息服务(Java Message Service)结合到一个事务中，如清单 8 所示。</FONT></P><A name=IDADANIB><B><FONT size=2>清单 8. 将 MovieDAO 和 JMS 代码结合到一个事务中</FONT></B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE> <FONT size=2> UserTransaction utx = MovieUtil.getUserTransaction(); utx.begin(); batman = dao.createMovie("R", "2008", "Batman Reloaded"); publisher = new MessagePublisher(); publisher.publishTextMessage("I'll be back"); dao.updateMovie(topgun.getId(), "PG-13", topgun.getReleaseYear(), topgun.getTitle()); dao.deleteMovie(legallyblonde.getId()); utx.commit(); </FONT></CODE></PRE></TD></TR></TBODY></TABLE>
<P><FONT size=2>要运行这个演示应用程序，需要在应用服务器上配置一个 XA 数据源和一个非 XA 数据源。然后，部署 daoexamples.ear 文件。这个应用程序可以在任何兼容 J2EE 1.3 的应用服务器上运行。参阅</FONT><A href="http://www-900.ibm.com/developerworks/cn/java/j-dao/#resources" xmlns=""><FONT size=2>参考资料</FONT></A><FONT size=2>以获得 EAR 文件和源代码。</FONT></P>
<P><A name=IDATANIB><SPAN class=atitle2><FONT size=2>结束语</FONT></SPAN></A><BR><FONT size=2>正如本文所展示的，实现 DAO 模式需要做比编写低级别的数据访问代码更多的工作。现在，通过选择一个适合您的应用程序的事务界定策略、通过在 DAO 类中加入日志记录，以及通过遵从几项简单的异常处理原则，您可以构建更好的 DAO。</FONT></P>
<P><A name=resources><SPAN class=atitle2><FONT size=2>参考资料</FONT></SPAN></A><FONT size=2> </FONT>
<UL>
<LI><FONT size=2>从 </FONT><A href="http://daoexamples.sourceforge.net/" xmlns=""><FONT size=2>daoexamples.sourceforge.net</FONT></A><FONT size=2>上下载 MovieDAO 源代码。<BR><BR></FONT>
<LI><FONT size=2>想要学习有关数据访问对象模式的更多内容？可以从</FONT><A href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" xmlns=""><FONT size=2>核心 J2EE 模式主页</FONT></A><FONT size=2>开始。<BR><BR></FONT>
<LI><FONT size=2>Kyle Brown 的“</FONT><A href="http://www.ibm.com/developerworks/java/library/j-sdao/" xmlns=""><FONT size=2>A stepped approach to J2EE testing with SDAO</FONT></A><FONT size=2>”(<I xmlns="">developerWorks</I>，2003 年 3 月)提供了对数据访问对象和 DAO 设计模式的简要介绍。<BR><BR></FONT>
<LI><FONT size=2>Dragonslayer 的教程“</FONT><A href="http://www-106.ibm.com/developerworks/ibm/edu/i-dw-i-2extreme6-i.html" xmlns=""><FONT size=2>Create persistent application data with Java Data Objects</FONT></A><FONT size=2>”(<I xmlns="">developerWorks</I>，2003 年 7 月)向您展示了如何结合 Struts 与 DAO 模式以用于影响小的企业数据持久性。<BR><BR></FONT>
<LI><FONT size=2>Srikanth Shenoy 的“</FONT><A href="http://www-900.ibm.com/developerWorks/cn/java/j-ejbexcept/" xmlns=""><FONT size=2>EJB 异常处理的最佳做法</FONT></A><FONT size=2>”(<I xmlns="">developerWorks</I>，2002 年 5 月)介绍了异常处理基础和使用 Log4J 进行日志记录。<BR><BR></FONT>
<LI><FONT size=2><I xmlns="">Java 理论与实践系列</I>从“</FONT><A href="http://www-106.ibm.com/developerworks/java/library/j-jtp0305.html" xmlns=""><FONT size=2>理解 JTS -- 事务处理简介</FONT></A><FONT size=2>”开始(<I xmlns="">developerWorks</I>，2002年3月)提供了对 Java 事务 API 的三部分介绍。<BR><BR></FONT>
<LI><A href="http://java.sun.com/products/jta/" xmlns=""><FONT size=2>Java Transaction API</FONT></A><FONT size=2> 是 J2EE 平台的关键部分。<BR><BR></FONT>
<LI><A href="http://jakarta.apache.org/log4j/" xmlns=""><FONT size=2>Jakarta Log4j</FONT></A><FONT size=2> 是 Java 应用程序的世界级日志库。<BR><BR></FONT>
<LI><A href="http://jakarta.apache.org/commons/logging.html" xmlns=""><FONT size=2>Jakarta Commons Logging</FONT></A><FONT size=2> 提供了容易使用的日志抽象层。<BR><BR></FONT>
<LI><A href="http://www.springframework.org/" xmlns=""><FONT size=2>Spring Framework</FONT></A><FONT size=2> 为 JDBC 和事务管理提供了抽象层。此外，这个框架包含标准的 DAO 异常类和 JNDI 帮助器类。<BR><BR></FONT>
<LI><FONT size=2>Rod Johnson 的</FONT><A href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/" xmlns=""><I><FONT size=2>J2EE Design and Development</FONT></I></A><FONT size=2> (Wrox Press，2002 年)是每一位 J2EE 开发人员都应该收藏的。本书充满了应用程序设计策略、实用编程技巧和实际的例子。<BR><BR></FONT>
<LI><FONT size=2>Josh Bloch 的</FONT><A href="http://www.amazon.com/exec/obidos/tg/detail/-/0201310058/" xmlns=""><I><FONT size=2> Effective Java Programming Language Guide</FONT></I></A><FONT size=2> (Addison Wesley，2001 年)展示了异常处理和类库设计的最佳实践。<BR><BR></FONT></LI></UL></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jelver/aggbug/32010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-22 20:29 <a href="http://www.blogjava.net/jelver/articles/32010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>