﻿<?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-水煮三国-随笔分类-Hibernate</title><link>http://www.blogjava.net/os586/category/12511.html</link><description>态度决定一切，思想决定出路</description><language>zh-cn</language><lastBuildDate>Thu, 21 Jun 2007 14:07:12 GMT</lastBuildDate><pubDate>Thu, 21 Jun 2007 14:07:12 GMT</pubDate><ttl>60</ttl><item><title>Hibernate的类型怎样映射数据库中字段的自定义类型</title><link>http://www.blogjava.net/os586/archive/2007/06/21/125586.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Thu, 21 Jun 2007 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2007/06/21/125586.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/125586.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2007/06/21/125586.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/125586.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/125586.html</trackback:ping><description><![CDATA[
		<textarea class="content" style="WIDTH: 698px; HEIGHT: 137px" rows="7" readonly="" cols="74">我在数据库中自定义了数据类型：如UserName,其实它就是一个基本数据类型：varchar(12)的。

但是这种自定义数据类型在hibernate当中我们该怎样进行数据类型的映射？
</textarea>
<img src ="http://www.blogjava.net/os586/aggbug/125586.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2007-06-21 15:48 <a href="http://www.blogjava.net/os586/archive/2007/06/21/125586.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再论Domaion Object [From JavaEye]</title><link>http://www.blogjava.net/os586/archive/2006/10/19/76082.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Thu, 19 Oct 2006 02:01:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/10/19/76082.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/76082.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/10/19/76082.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/76082.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/76082.html</trackback:ping><description><![CDATA[
		<p>既然大家都统一了观点，那么就有了一个很好的讨论问题的基础了。Martin Fowler的Domain Model，或者说我们的第二种模型难道是完美无缺的吗？当然不是，接下来我就要分析一下它的不足，以及可能的解决办法，而这些都来源于我个人的实践探索。</p>
		<p>在第二种模型中，我们可以清楚的把这4个类分为三层：</p>
		<p>1、实体类层，即Item，带有domain logic的domain object <br />2、DAO层，即ItemDao和ItemDaoHibernateImpl，抽象持久化操作的接口和实现类 <br />3、业务逻辑层，即ItemManager，接受容器事务控制，向Web层提供统一的服务调用</p>
		<p>在这三层中我们大家可以看到，domain object和DAO都是非常稳定的层，其实原因也很简单，因为domain object是映射数据库字段的，数据库字段不会频繁变动，所以domain object也相对稳定，而面向数据库持久化编程的DAO层也不过就是CRUD而已，不会有更多的花样，所以也很稳定。</p>
		<p>问题就在于这个充当business workflow facade的业务逻辑对象，它的变动是相当频繁的。<span style="COLOR: red">业务逻辑对象通常都是无状态的、受事务控制的、Singleton类</span>，我们可以考察一下业务逻辑对象都有哪几类业务逻辑方法：</p>
		<p>
				<span style="COLOR: red">第一类：DAO接口方法的代理</span>，就是上面例子中的loadItemById方法和findAll方法。</p>
		<p>ItemManager之所以要代理这种类，目的有两个：<span style="COLOR: red">向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功能</span>。这两点都很容易理解，你不能既给Web层程序员提供xxxManager，也给他提供xxxDao，所以你需要用xxxManager封装xxxDao，在这里，充当了一个简单代理功能；而事务控制也是持久化方法必须的，事务可能需要跨越多个DAO方法调用，所以必须放在业务逻辑层，而不能放在DAO层。</p>
		<p>但是必须看到，对于一个典型的web应用来说，绝大多数的业务逻辑都是简单的CRUD逻辑，所以这种情况下，针对每个DAO方法，xxxManager都需要提供一个对应的封装方法，这不但是非常枯燥的，也是令人感觉非常不好的。</p>
		<p>
				<span style="COLOR: red">第二类：domain logic的方法代理</span>。就是上面例子中placeBid方法。虽然Item已经有了placeBid方法，但是ItemManager仍然需要封装一下Item的placeBid，然后再提供一个简单封装之后的代理方法。</p>
		<p>这和第一种情况类似，其原因也一样，也是为了给Web层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制。</p>
		<p>同样，和第一种情况一样，针对每个domain logic方法，xxxManager都需要提供一个对应的封装方法，同样是枯燥的，令人不爽的。</p>
		<p>
				<span style="COLOR: red">第三类：需要多个domain object和DAO参与协作的business workflow</span>。这种情况是业务逻辑对象真正应该完成的职责。</p>
		<p>在这个简单的例子中，没有涉及到这种情况，不过大家都可以想像的出来这种应用场景，因此不必举例说明了。</p>
		<p>通过上面的分析可以看出，只有第三类业务逻辑方法才是业务逻辑对象真正应该承担的职责，而前两类业务逻辑方法都是“无奈之举”，不得不为之的事情，不但枯燥，而且令人沮丧。</p>
		<p>分析完了业务逻辑对象，我们再回头看一下domain object，我们要仔细考察一下domain logic的话，会发现domain logic也分为两类：</p>
		<p>
				<span style="COLOR: red">第一类：需要持久层框架隐式的实现透明持久化的domain logic</span>，例如Item的placeBid方法中的这一句： <br /></p>
		<div class="code_title">代码</div>
		<div class="code_div">
				<pre>
						<span class="ident">this</span>
						<span class="punct">.</span>
						<span class="ident">getBids</span>
						<span class="punct">().</span>
						<span class="ident">add</span>
						<span class="punct">(</span>
						<span class="ident">newBid</span>
						<span class="punct">);</span>
				</pre>
		</div>
		<br />上面已经着重提到，虽然这仅仅只是一个Java集合的添加新元素的操作，但是实际上通过事务的控制，会潜在的触发两条SQL：一条是insert一条记录到bid表，一条是更新item表相应的记录。如果我们让Item脱离Hibernate进行单元测试，它就是一个单纯的Java集合操作，如果我们把他加入到Hibernate框架中，他就会潜在的触发两条SQL，<span style="COLOR: red">这就是隐式的依赖于持久化的domain logic</span>。 <br />特别请注意的一点是：在没有Hibernate/JDO这类可以实现“透明的持久化”工具出现之前，这类domain logic是无法实现的。 
<p></p><p>对于这一类domain logic，业务逻辑对象必须提供相应的封装方法，以实现事务控制。</p><p><span style="COLOR: red">第二类：完全不依赖持久化的domain logic</span>，例如readonly例子中的Topic，如下：</p><p></p><div class="code_title">java代码</div><div class="code_div"><pre><span class="keyword">class </span><span class="class">Topic</span><span class="punct">{</span><br /><span class="ident">boolean</span><span class="ident">isAllowReply</span><span class="punct">()</span><span class="punct">{</span><br /><span class="constant">Calendar</span><span class="ident">dueDate</span><span class="punct">=</span><span class="constant">Calendar</span><span class="punct">.</span><span class="ident">getInstance</span><span class="punct">();</span><br /><span class="ident">dueDate</span><span class="punct">.</span><span class="ident">setTime</span><span class="punct">(</span><span class="ident">lastUpdatedTime</span><span class="punct">);</span><br /><span class="ident">dueDate</span><span class="punct">.</span><span class="ident">add</span><span class="punct">(</span><span class="constant">Calendar</span><span class="punct">.</span><span class="ident">DATE</span><span class="punct">,</span><span class="ident">forum</span><span class="punct">.</span><span class="ident">timeToLive</span><span class="punct">);</span><br /><br /><span class="constant">Date</span><span class="ident">now</span><span class="punct">=</span><span class="keyword">new</span><span class="constant">Date</span><span class="punct">();</span><br /><span class="keyword">return</span><span class="ident">now</span><span class="punct">.</span><span class="ident">after</span><span class="punct">(</span><span class="ident">dueDate</span><span class="punct">.</span><span class="ident">getTime</span><span class="punct">());</span><br /><span class="punct">}</span><br /><span class="punct">}</span></pre></div><p></p><p>注意这个isAllowReply方法，他和持久化完全不发生一丁点关系。在实际的开发中，我们同样会遇到很多这种不需要持久化的业务逻辑(主要发生在日期运算、数值运算和枚举运算方面)，这种domain logic不管脱离不脱离所在的框架，它的行为都是一致的。对于这种domain logic，业务逻辑层并不需要提供封装方法，它可以适用于任何场合。</p><img src ="http://www.blogjava.net/os586/aggbug/76082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-10-19 10:01 <a href="http://www.blogjava.net/os586/archive/2006/10/19/76082.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>总结一下最近关于domain object以及相关的讨论 [From:JAVAEYE]</title><link>http://www.blogjava.net/os586/archive/2006/10/19/76070.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Thu, 19 Oct 2006 01:19:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/10/19/76070.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/76070.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/10/19/76070.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/76070.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/76070.html</trackback:ping><description><![CDATA[
		<p>在最近的围绕domain object的讨论中浮现出来了三种模型，(还有一些其他的旁枝，不一一分析了)，经过一番讨论，各种问题逐渐清晰起来，在这里我试图做一个总结，便于大家了解和掌握。</p>
		<p>第一种模型：只有getter/setter方法的纯数据类，所有的业务逻辑完全由business object来完成(又称TransactionScript)，这种模型下的domain object被Martin Fowler称之为“贫血的domain object”。下面用举一个具体的代码来说明，代码来自Hibernate的caveatemptor，但经过我的改写：</p>
		<p>一个实体类叫做Item，指的是一个拍卖项目 <br />一个DAO接口类叫做ItemDao <br />一个DAO接口实现类叫做ItemDaoHibernateImpl <br />一个业务逻辑类叫做ItemManager(或者叫做ItemService) </p>
		<p>
		</p>
		<div class="code_title">java代码</div>
		<div class="code_div">
				<pre>
						<span class="keyword">public</span>
						<span class="keyword">class </span>
						<span class="class">Item</span>
						<span class="keyword">implements</span>
						<span class="constant">Serializable</span>
						<span class="punct">{</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Long</span>
						<span class="ident">id</span>
						<span class="punct">=</span>
						<span class="keyword">null</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="ident">int</span>
						<span class="ident">version</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">String</span>
						<span class="ident">name</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">User</span>
						<span class="ident">seller</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">String</span>
						<span class="ident">description</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">MonetaryAmount</span>
						<span class="ident">initialPrice</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">MonetaryAmount</span>
						<span class="ident">reservePrice</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Date</span>
						<span class="ident">startDate</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Date</span>
						<span class="ident">endDate</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Set</span>
						<span class="ident">categorizedItems</span>
						<span class="punct">=</span>
						<span class="keyword">new</span>
						<span class="constant">HashSet</span>
						<span class="punct">();</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Collection</span>
						<span class="ident">bids</span>
						<span class="punct">=</span>
						<span class="keyword">new</span>
						<span class="constant">ArrayList</span>
						<span class="punct">();</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Bid</span>
						<span class="ident">successfulBid</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">ItemState</span>
						<span class="ident">state</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">User</span>
						<span class="ident">approvedBy</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Date</span>
						<span class="ident">approvalDatetime</span>
						<span class="punct">;</span>
						<br />
						<span class="keyword">private</span>
						<span class="constant">Date</span>
						<span class="ident">created</span>
						<span class="punct">=</span>
						<span class="keyword">new</span>
						<span class="constant">Date</span>
						<span class="punct">();</span>
						<br />
						<span class="punct">/</span>
						<span class="regex">
						</span>
						<span class="punct">/</span>
						<span class="ident">getter</span>
						<span class="punct">/</span>
						<span class="ident">setter方法省略不写，避免篇幅太长</span>
						<br />
						<span class="punct">}</span>
				</pre>
		</div>
		<p>
		</p>
		<p>
		</p>
		<div class="code_title">java代码</div>
		<div class="code_div">
				<pre>
						<span class="keyword">public</span>
						<span class="keyword">interface</span>
						<span class="constant">ItemDao</span>
						<span class="punct">{</span>
						<br />
						<span class="keyword">public</span>
						<span class="constant">Item</span>
						<span class="ident">getItemById</span>
						<span class="punct">(</span>
						<span class="constant">Long</span>
						<span class="ident">id</span>
						<span class="punct">);</span>
						<br />
						<span class="keyword">public</span>
						<span class="constant">Collection</span>
						<span class="ident">findAll</span>
						<span class="punct">();</span>
						<br />
						<span class="keyword">public</span>
						<span class="ident">void</span>
						<span class="ident">updateItem</span>
						<span class="punct">(</span>
						<span class="constant">Item</span>
						<span class="ident">item</span>
						<span class="punct">);</span>
						<br />
						<span class="punct">}</span>
				</pre>
		</div>
		<p>
		</p>
		<p>ItemDao定义持久化操作的接口，用于隔离持久化代码。</p>
		<p>
		</p>
		<div class="code_title">java代码</div>
		<div class="code_div">
				<pre>
						<span class="keyword">public</span>
						<span class="keyword">class </span>
						<span class="class">ItemDaoHibernateImpl</span>
						<span class="keyword">implements</span>
						<span class="constant">ItemDao</span>
						<span class="keyword">extends</span>
						<span class="constant">HibernateDaoSupport</span>
						<span class="punct">{</span>
						<br />
						<span class="keyword">public</span>
						<span class="constant">Item</span>
						<span class="ident">getItemById</span>
						<span class="punct">(</span>
						<span class="constant">Long</span>
						<span class="ident">id</span>
						<span class="punct">)</span>
						<span class="punct">{</span>
						<br />
						<span class="keyword">return</span>
						<span class="punct">(</span>
						<span class="constant">Item</span>
						<span class="punct">)</span>
						<span class="ident">getHibernateTemplate</span>
						<span class="punct">().</span>
						<span class="ident">load</span>
						<span class="punct">(</span>
						<span class="constant">Item</span>
						<span class="punct">.</span>
						<span class="ident">class</span>
						<span class="punct">,</span>
						<span class="ident">id</span>
						<span class="punct">);</span>
						<br />
						<span class="punct">}</span>
						<br />
						<span class="keyword">public</span>
						<span class="constant">Collection</span>
						<span class="ident">findAll</span>
						<span class="punct">()</span>
						<span class="punct">{</span>
						<br />
						<span class="keyword">return</span>
						<span class="punct">(</span>
						<span class="constant">List</span>
						<span class="punct">)</span>
						<span class="ident">getHibernateTemplate</span>
						<span class="punct">().</span>
						<span class="ident">find</span>
						<span class="punct">("</span>
						<span class="string">from Item</span>
						<span class="punct">");</span>
						<br />
						<span class="punct">}</span>
						<br />
						<span class="keyword">public</span>
						<span class="ident">void</span>
						<span class="ident">updateItem</span>
						<span class="punct">(</span>
						<span class="constant">Item</span>
						<span class="ident">item</span>
						<span class="punct">)</span>
						<span class="punct">{</span>
						<br />
						<span class="ident">getHibernateTemplate</span>
						<span class="punct">().</span>
						<span class="ident">update</span>
						<span class="punct">(</span>
						<span class="ident">item</span>
						<span class="punct">);</span>
						<br />
						<span class="punct">}</span>
						<br />
						<span class="punct">}</span>
				</pre>
		</div>
		<br />ItemDaoHibernateImpl完成具体的持久化工作，请注意，数据库资源的获取和释放是在ItemDaoHibernateImpl里面处理的，每个DAO方法调用之前打开Session，DAO方法调用之后，关闭Session。(Session放在ThreadLocal中，保证一次调用只打开关闭一次) 
<p></p><p></p><div class="code_title">java代码</div><div class="code_div"><pre><span class="keyword">public</span><span class="keyword">class </span><span class="class">ItemManager</span><span class="punct">{</span><br /><span class="keyword">private</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">;</span><br /><span class="keyword">public</span><span class="ident">void</span><span class="ident">setItemDao</span><span class="punct">(</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">)</span><span class="punct">{</span><span class="ident">this</span><span class="punct">.</span><span class="ident">itemDao</span><span class="punct">=</span><span class="ident">itemDao</span><span class="punct">;}</span><br /><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="constant">Long</span><span class="ident">id</span><span class="punct">)</span><span class="punct">{</span><br /><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="ident">id</span><span class="punct">);</span><br /><span class="punct">}</span><br /><span class="keyword">public</span><span class="constant">Collection</span><span class="ident">listAllItems</span><span class="punct">()</span><span class="punct">{</span><br /><span class="keyword">return</span><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">findAll</span><span class="punct">();</span><br /><span class="punct">}</span><br /><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">placeBid</span><span class="punct">(</span><span class="constant">Item</span><span class="ident">item</span><span class="punct">,</span><span class="constant">User</span><span class="ident">bidder</span><span class="punct">,</span><span class="constant">MonetaryAmount</span><span class="ident">bidAmount</span><span class="punct">,</span><br /><span class="constant">Bid</span><span class="ident">currentMaxBid</span><span class="punct">,</span><span class="constant">Bid</span><span class="ident">currentMinBid</span><span class="punct">)</span><span class="keyword">throws</span><span class="constant">BusinessException</span><span class="punct">{</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">currentMaxBid</span><span class="punct">!=</span><span class="keyword">null</span><span class="punct">&amp;&amp;</span><span class="ident">currentMaxBid</span><span class="punct">.</span><span class="ident">getAmount</span><span class="punct">().</span><span class="ident">compareTo</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">)</span><span class="punct">&gt;</span><span class="number">0</span><span class="punct">)</span><span class="punct">{</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Bid too low.</span><span class="punct">");</span><br /><span class="punct">}</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">is</span><span class="ident">active</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="punct">!</span><span class="ident">state</span><span class="punct">.</span><span class="ident">equals</span><span class="punct">(</span><span class="constant">ItemState</span><span class="punct">.</span><span class="ident">ACTIVE</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Auction is not active yet.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">still</span><span class="ident">valid</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">item</span><span class="punct">.</span><span class="ident">getEndDate</span><span class="punct">().</span><span class="ident">before</span><span class="punct">(</span><span class="keyword">new</span><span class="constant">Date</span><span class="punct">()</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Can't place new bid, auction already ended.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Create</span><span class="keyword">new</span><span class="constant">Bid</span><br /><span class="constant">Bid</span><span class="ident">newBid</span><span class="punct">=</span><span class="keyword">new</span><span class="constant">Bid</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">,</span><span class="ident">item</span><span class="punct">,</span><span class="ident">bidder</span><span class="punct">);</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Place</span><span class="ident">bid</span><span class="keyword">for</span><span class="ident">this</span><span class="constant">Item</span><br /><span class="ident">item</span><span class="punct">.</span><span class="ident">getBids</span><span class="punct">().</span><span class="ident">add</span><span class="punct">(</span><span class="ident">newBid</span><span class="punct">);</span><br /><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">update</span><span class="punct">(</span><span class="ident">item</span><span class="punct">);</span><span class="punct">/</span><span class="regex"></span><span class="punct">/</span>  调用<span class="constant">DAO完成持久化操作</span><br /><span class="keyword">return</span><span class="ident">newBid</span><span class="punct">;</span><br /><span class="punct">}</span><br /><span class="punct">}</span></pre></div><p></p><p>事务的管理是在ItemManger这一层完成的，ItemManager实现具体的业务逻辑。除了常见的和CRUD有关的简单逻辑之外，这里还有一个placeBid的逻辑，即项目的竞标。</p><p>以上是一个完整的第一种模型的示例代码。在这个示例中，placeBid，loadItemById，findAll等等业务逻辑统统放在ItemManager中实现，而Item只有getter/setter方法。<br /><br /><br /><br /><br /><br /></p><p>第二种模型，也就是Martin Fowler指的rich domain object是下面这样子的：</p><p>一个带有业务逻辑的实体类，即domain object是Item <br />一个DAO接口ItemDao <br />一个DAO实现ItemDaoHibernateImpl <br />一个业务逻辑对象ItemManager</p><p></p><div class="code_title">java代码</div><div class="code_div"><pre><span class="keyword">public</span><span class="keyword">class </span><span class="class">Item</span><span class="keyword">implements</span><span class="constant">Serializable</span><span class="punct">{</span><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span>  所有的属性和<span class="ident">getter</span><span class="punct">/</span><span class="ident">setter方法同上，省略</span><br /><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">placeBid</span><span class="punct">(</span><span class="constant">User</span><span class="ident">bidder</span><span class="punct">,</span><span class="constant">MonetaryAmount</span><span class="ident">bidAmount</span><span class="punct">,</span><br /><span class="constant">Bid</span><span class="ident">currentMaxBid</span><span class="punct">,</span><span class="constant">Bid</span><span class="ident">currentMinBid</span><span class="punct">)</span><br /><span class="keyword">throws</span><span class="constant">BusinessException</span><span class="punct">{</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Check</span><span class="ident">highest</span><span class="ident">bid</span><span class="punct">(</span><span class="ident">can</span><span class="ident">also</span><span class="ident">be</span><span class="ident">a</span><span class="ident">different</span><span class="constant">Strategy</span><span class="punct">(</span><span class="ident">pattern</span><span class="punct">))</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">currentMaxBid</span><span class="punct">!=</span><span class="keyword">null</span><span class="punct">&amp;&amp;</span><span class="ident">currentMaxBid</span><span class="punct">.</span><span class="ident">getAmount</span><span class="punct">().</span><span class="ident">compareTo</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">)</span><span class="punct">&gt;</span><span class="number">0</span><span class="punct">)</span><span class="punct">{</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Bid too low.</span><span class="punct">");</span><br /><span class="punct">}</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">is</span><span class="ident">active</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="punct">!</span><span class="ident">state</span><span class="punct">.</span><span class="ident">equals</span><span class="punct">(</span><span class="constant">ItemState</span><span class="punct">.</span><span class="ident">ACTIVE</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Auction is not active yet.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">still</span><span class="ident">valid</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">this</span><span class="punct">.</span><span class="ident">getEndDate</span><span class="punct">().</span><span class="ident">before</span><span class="punct">(</span><span class="keyword">new</span><span class="constant">Date</span><span class="punct">()</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Can't place new bid, auction already ended.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Create</span><span class="keyword">new</span><span class="constant">Bid</span><br /><span class="constant">Bid</span><span class="ident">newBid</span><span class="punct">=</span><span class="keyword">new</span><span class="constant">Bid</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">,</span><span class="ident">this</span><span class="punct">,</span><span class="ident">bidder</span><span class="punct">);</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Place</span><span class="ident">bid</span><span class="keyword">for</span><span class="ident">this</span><span class="constant">Item</span><br /><span class="ident">this</span><span class="punct">.</span><span class="ident">getBids</span><span class="punct">.</span><span class="ident">add</span><span class="punct">(</span><span class="ident">newBid</span><span class="punct">);</span><span class="punct">/</span><span class="regex"></span><span class="punct">/</span> 请注意这一句，透明的进行了持久化，但是不能在这里调用<span class="constant">ItemDao，Item不能对ItemDao产生依赖！</span><br /><br /><span class="keyword">return</span><span class="ident">newBid</span><span class="punct">;</span><br /><span class="punct">}</span><br /><span class="punct">}</span></pre></div><p></p><p>竞标这个业务逻辑被放入到Item中来。请注意this.getBids.add(newBid); 如果没有Hibernate或者JDO这种O/R Mapping的支持，我们是无法实现这种透明的持久化行为的。但是请注意，Item里面不能去调用ItemDAO，对ItemDAO产生依赖！</p><p>ItemDao和ItemDaoHibernateImpl的代码同上，省略。</p><p></p><div class="code_title">java代码</div><div class="code_div"><pre><span class="keyword">public</span><span class="keyword">class </span><span class="class">ItemManager</span><span class="punct">{</span><br /><span class="keyword">private</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">;</span><br /><span class="keyword">public</span><span class="ident">void</span><span class="ident">setItemDao</span><span class="punct">(</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">)</span><span class="punct">{</span><span class="ident">this</span><span class="punct">.</span><span class="ident">itemDao</span><span class="punct">=</span><span class="ident">itemDao</span><span class="punct">;}</span><br /><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="constant">Long</span><span class="ident">id</span><span class="punct">)</span><span class="punct">{</span><br /><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="ident">id</span><span class="punct">);</span><br /><span class="punct">}</span><br /><span class="keyword">public</span><span class="constant">Collection</span><span class="ident">listAllItems</span><span class="punct">()</span><span class="punct">{</span><br /><span class="keyword">return</span><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">findAll</span><span class="punct">();</span><br /><span class="punct">}</span><br /><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">placeBid</span><span class="punct">(</span><span class="constant">Item</span><span class="ident">item</span><span class="punct">,</span><span class="constant">User</span><span class="ident">bidder</span><span class="punct">,</span><span class="constant">MonetaryAmount</span><span class="ident">bidAmount</span><span class="punct">,</span><br /><span class="constant">Bid</span><span class="ident">currentMaxBid</span><span class="punct">,</span><span class="constant">Bid</span><span class="ident">currentMinBid</span><span class="punct">)</span><span class="keyword">throws</span><span class="constant">BusinessException</span><span class="punct">{</span><br /><span class="ident">item</span><span class="punct">.</span><span class="ident">placeBid</span><span class="punct">(</span><span class="ident">bidder</span><span class="punct">,</span><span class="ident">bidAmount</span><span class="punct">,</span><span class="ident">currentMaxBid</span><span class="punct">,</span><span class="ident">currentMinBid</span><span class="punct">);</span><br /><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">update</span><span class="punct">(</span><span class="ident">item</span><span class="punct">);</span><span class="punct">/</span><span class="regex"></span><span class="punct">/</span> 必须显式的调用<span class="constant">DAO，保持持久化</span><br /><span class="punct">}</span><br /><span class="punct">}</span></pre></div><p></p><p>在第二种模型中，placeBid业务逻辑是放在Item中实现的，而loadItemById和findAll业务逻辑是放在ItemManager中实现的。不过值得注意的是，即使placeBid业务逻辑放在Item中，你仍然需要在ItemManager中简单的封装一层，以保证对placeBid业务逻辑进行事务的管理和持久化的触发。</p><p>这种模型是Martin Fowler所指的真正的domain model。在这种模型中，有三个业务逻辑方法：placeBid，loadItemById和findAll，现在的问题是哪个逻辑应该放在Item中，哪个逻辑应该放在ItemManager中。在我们这个例子中，placeBid放在Item中(但是ItemManager也需要对它进行简单的封装)，loadItemById和findAll是放在ItemManager中的。</p><p>切分的原则是什么呢？ Rod Johnson提出原则是“case by case”，可重用度高的，和domain object状态密切关联的放在Item中，可重用度低的，和domain object状态没有密切关联的放在ItemManager中。</p><p><span style="COLOR: red">我提出的原则是：看业务方法是否显式的依赖持久化。</span></p><p>Item的placeBid这个业务逻辑方法没有显式的对持久化ItemDao接口产生依赖，所以要放在Item中。<span style="COLOR: red">请注意，如果脱离了Hibernate这个持久化框架，Item这个domain object是可以进行单元测试的，他不依赖于Hibernate的持久化机制。它是一个独立的，可移植的，完整的，自包含的域对象</span>。</p><p>而loadItemById和findAll这两个业务逻辑方法是必须显式的对持久化ItemDao接口产生依赖，否则这个业务逻辑就无法完成。如果你要把这两个方法放在Item中，那么Item就无法脱离Hibernate框架，无法在Hibernate框架之外独立存在。<br /><br /><br /><br /></p><p>第三种模型印象中好像是firebody或者是Archie提出的(也有可能不是，记不清楚了)，简单的来说，这种模型就是把第二种模型的domain object和business object合二为一了。所以ItemManager就不需要了，在这种模型下面，只有三个类，他们分别是：</p><p>Item：包含了实体类信息，也包含了所有的业务逻辑 <br />ItemDao：持久化DAO接口类 <br />ItemDaoHibernateImpl：DAO接口的实现类</p><p>由于ItemDao和ItemDaoHibernateImpl和上面完全相同，就省略了。</p><p></p><div class="code_title">java代码</div><div class="code_div"><pre><span class="keyword">public</span><span class="keyword">class </span><span class="class">Item</span><span class="keyword">implements</span><span class="constant">Serializable</span><span class="punct">{</span><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span>  所有的属性和<span class="ident">getter</span><span class="punct">/</span><span class="ident">setter方法都省略</span><br /><span class="keyword">private</span><span class="ident">static</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">;</span><br /><span class="keyword">public</span><span class="ident">void</span><span class="ident">setItemDao</span><span class="punct">(</span><span class="constant">ItemDao</span><span class="ident">itemDao</span><span class="punct">)</span><span class="punct">{</span><span class="ident">this</span><span class="punct">.</span><span class="ident">itemDao</span><span class="punct">=</span><span class="ident">itemDao</span><span class="punct">;}</span><br /><br /><span class="keyword">public</span><span class="ident">static</span><span class="constant">Item</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="constant">Long</span><span class="ident">id</span><span class="punct">)</span><span class="punct">{</span><br /><span class="keyword">return</span><span class="punct">(</span><span class="constant">Item</span><span class="punct">)</span><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">loadItemById</span><span class="punct">(</span><span class="ident">id</span><span class="punct">);</span><br /><span class="punct">}</span><br /><span class="keyword">public</span><span class="ident">static</span><span class="constant">Collection</span><span class="ident">findAll</span><span class="punct">()</span><span class="punct">{</span><br /><span class="keyword">return</span><span class="punct">(</span><span class="constant">List</span><span class="punct">)</span><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">findAll</span><span class="punct">();</span><br /><span class="punct">}</span><p></p><p><span class="keyword">public</span><span class="constant">Bid</span><span class="ident">placeBid</span><span class="punct">(</span><span class="constant">User</span><span class="ident">bidder</span><span class="punct">,</span><span class="constant">MonetaryAmount</span><span class="ident">bidAmount</span><span class="punct">,</span><br /><span class="constant">Bid</span><span class="ident">currentMaxBid</span><span class="punct">,</span><span class="constant">Bid</span><span class="ident">currentMinBid</span><span class="punct">)</span><br /><span class="keyword">throws</span><span class="constant">BusinessException</span><span class="punct">{</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Check</span><span class="ident">highest</span><span class="ident">bid</span><span class="punct">(</span><span class="ident">can</span><span class="ident">also</span><span class="ident">be</span><span class="ident">a</span><span class="ident">different</span><span class="constant">Strategy</span><span class="punct">(</span><span class="ident">pattern</span><span class="punct">))</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">currentMaxBid</span><span class="punct">!=</span><span class="keyword">null</span><span class="punct">&amp;&amp;</span><span class="ident">currentMaxBid</span><span class="punct">.</span><span class="ident">getAmount</span><span class="punct">().</span><span class="ident">compareTo</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">)</span><span class="punct">&gt;</span><span class="number">0</span><span class="punct">)</span><span class="punct">{</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Bid too low.</span><span class="punct">");</span><br /><span class="punct">}</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">is</span><span class="ident">active</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="punct">!</span><span class="ident">state</span><span class="punct">.</span><span class="ident">equals</span><span class="punct">(</span><span class="constant">ItemState</span><span class="punct">.</span><span class="ident">ACTIVE</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Auction is not active yet.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Auction</span><span class="ident">still</span><span class="ident">valid</span><br /><span class="keyword">if</span><span class="punct">(</span><span class="ident">this</span><span class="punct">.</span><span class="ident">getEndDate</span><span class="punct">().</span><span class="ident">before</span><span class="punct">(</span><span class="keyword">new</span><span class="constant">Date</span><span class="punct">()</span><span class="punct">)</span><span class="punct">)</span><br /><span class="ident">throw</span><span class="keyword">new</span><span class="constant">BusinessException</span><span class="punct">("</span><span class="string">Can't place new bid, auction already ended.</span><span class="punct">");</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Create</span><span class="keyword">new</span><span class="constant">Bid</span><br /><span class="constant">Bid</span><span class="ident">newBid</span><span class="punct">=</span><span class="keyword">new</span><span class="constant">Bid</span><span class="punct">(</span><span class="ident">bidAmount</span><span class="punct">,</span><span class="ident">this</span><span class="punct">,</span><span class="ident">bidder</span><span class="punct">);</span><br /><br /><span class="punct">/</span><span class="regex"></span><span class="punct">/</span><span class="constant">Place</span><span class="ident">bid</span><span class="keyword">for</span><span class="ident">this</span><span class="constant">Item</span><br /><span class="ident">this</span><span class="punct">.</span><span class="ident">addBid</span><span class="punct">(</span><span class="ident">newBid</span><span class="punct">);</span><br /><span class="ident">itemDao</span><span class="punct">.</span><span class="ident">update</span><span class="punct">(</span><span class="ident">this</span><span class="punct">);</span><span class="punct">/</span><span class="regex"></span><span class="punct">/</span>  调用<span class="constant">DAO进行显式持久化</span><br /><span class="keyword">return</span><span class="ident">newBid</span><span class="punct">;</span><br /><span class="punct">}</span><br /><span class="punct">}</span></p></pre></div><p></p><p>在这种模型中，所有的业务逻辑全部都在Item中，事务管理也在Item中实现。</p><img src ="http://www.blogjava.net/os586/aggbug/76070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-10-19 09:19 <a href="http://www.blogjava.net/os586/archive/2006/10/19/76070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Pro Hibernate 3笔记和小结（2）之第一章Hibernate3介绍</title><link>http://www.blogjava.net/os586/archive/2006/07/28/60487.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Fri, 28 Jul 2006 02:06:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/07/28/60487.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/60487.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/07/28/60487.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/60487.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/60487.html</trackback:ping><description><![CDATA[
		<strong>Pro Hibernate 3笔记和小结（2）之第一章Hibernate3介绍<br /><br /></strong>
		<span class="tpc_content">
				<font style="font-size:12px">/**<br />作者：Willpower<br />来源：Rifoo Technology（</font>
				<a href="http://www.rifoo.com/" target="_blank">
						<font style="font-size:12px">http://www.rifoo.com</font>
				</a>
				<font size="2">）<br />时间：2006-05<br />备注：转载请保留以上声明<br />**/<br /><br /><br />今天继续第一章的学习，我们先来看看EJB和Hibernate的区别。<br /><br />为什么不用EJB来存储，显示，查询数据库中的数据呢？严格的说，EJB服务器支持两种类型的持久化，就是BEAN管理的持久化（BMP）和容器管理的持久化（CMP）。在BMP中，Bean自己负责执行所有的SQL语句来完成存储和查询数据。换句话说，我们自己要去编写JDBC逻辑代码。另一方面，CMP是由容器来执行存储和检索bean数据的工作。<br /><br />我们这里不选择EJB的原因如下：<br />1 CMP实体bean需要和数据表一对一的映射<br />2 它们很慢<br />3 有时候要人工参与的去决定哪一个bean字段对应表的哪一列<br />4 它们对方法命名有要求<br />5 EJB的容器是重量级的<br />6 它们和容器依赖强，不容易移植<br /><br />下面看看Hibernate的特点：<br />1 不需要强制映射一个POJO到一个表，不强制一对一的关系<br />2 尽快启动并加载它的配置文件时会对性能有些负载，但总的来说，它是很快的工具<br />3 和容器没有强依赖，很方便的移植<br />4 可以很轻松的处理serializable POJOs<br /><br />以上只是简单的列举，还有很多特点都没有提及。总之，Hibernate在应用程序的持久层这一块是非常不错的框架。下面我们来看一个Hibernate的Hello world程序：<br /><br />Listing 1-4. Hibernate检索POJO的范例代码<br /></font>
				<div style="FONT-SIZE: 9px; MARGIN-LEFT: 5px">
						<b>CODE:</b>
				</div>
				<div class="quote" id="code1">
						<br />public static Motd getMotd(int messageId)<br />                  throws MotdException<br />{<br />  SessionFactory sessions =<br />            new Configuration().configure().buildSessionFactory();<br />  Session session = sessions.openSession();<br />  Transaction tx = null;<br />  try {<br />    tx = session.beginTransaction();<br />    Motd motd =<br />            (Motd)session.get( Motd.class,<br />            new Integer(messageId));<br />    tx.commit();<br />    tx = null;<br />    return motd;<br />  } catch ( HibernateException e ) {<br />    if ( tx != null ) tx.rollback();<br />        log.log(Level.SEVERE, "Could not acquire message", e);<br />        throw new MotdException(<br />            "Failed to retrieve message from the database.",e);<br />  } finally {<br />    session.close();<br />  }<br />}<br /></div>
				<div style="FONT-SIZE: 11px; MARGIN-LEFT: 5px">
						<a onclick="CopyCode(document.getElementById('code1'));" href="javascript:">[Copy to clipboard]</a>
				</div>
				<br />
				<br />大家可以看到，代码量减少了很多，SessionFactory通常用于原来类似EJB的JNDI寻址操作。<br />由于messageId是Motd对象的主键，我们只用了一行代码就完成了数据的检索工作：<br /><br />Motd motd = (Motd)session.get(Motd.class, new Integer(messageId));<br /><br />如果不是直接关键主键的那些更复杂一些的查询，则需要使用SQL或HQL（Hibernate Query Language）。实际上，Hibernate3给我们提供了自动的事务和缓存的功能，因此，我们不用在出错处理上象JDBC那样编写过多的冗余代码了。<br /><br />Hibernate还需要知道哪个表来关联哪个对象，这个实际上由一个XML映射文件来提供的。尽管有些工具会造成大量的冗余难读懂的XML文件，但是Hibernate在这一块上处理非常轻巧，针对每个需要映射到数据库中的那些POJO对象，我们只需要创建一个简单而清晰的XML文件就可以了。当然，也可以将所有信息都放到一个大的XML文件中，Hibernate照样能读懂它们，可是这种做法不被推荐使用，因为可读和可维护性都太差了。<br /><br />一个文档类型定义（Document Type Definition，简称DTD）文件提供给所有的Hibernate配置文件，因此如果有好的XML编辑器，那么可以使用自动完成和自动验证XML的很多方便的功能来编辑XML配置文件，有些工具甚至可以自动创建这些配置文件。而Java 5中新加入的注释语法（annotations）能够完全取代它们。<br /><br />下面是我们的Motd POJO对象到数据库的映射文件：<br /><br />Listing 1-5. 映射POJO到数据库的XML文件<br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 5px"><b>CODE:</b></div><div class="quote" id="code2"><br />&lt;?xml version="1.0"?&gt;<br />&lt;!DOCTYPE hibernate-mapping PUBLIC<br />"-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />"[url]http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd[/url]"&gt;<br /><br />&lt;hibernate-mapping&gt;<br />  &lt;class name="Motd" table="Motd"&gt;<br />    &lt;id name="id" type="int" column="id"&gt;<br />        &lt;generator class="native"/&gt;<br />    &lt;/id&gt;<br />    &lt;property name="message" column="message" type="string"/&gt;<br />  &lt;/class&gt;<br />&lt;/hibernate-mapping&gt;<br /></div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 5px"><a onclick="CopyCode(document.getElementById('code2'));" href="javascript:">[Copy to clipboard]</a></div><br /><br />你可能会问，是不是将复杂性简单地从应用的代码转移到了XML映射文件中了呢？事实上并不是这样。<br />1 XML文件比从结果集返回的复杂的POJO对象更容易编辑和处理<br />2 使我们可以排除类似JDBC那样的错误处理机制的代码复杂性<br />3 最重要的是，如果POJO提供类似javabean那样的属性访问方法（即getter和setter方法），和一个默认的构造方法，那么Hibernate的工具可以方便的自动生成XML文件。关于工具的使用在第10章中讨论</span>
<img src ="http://www.blogjava.net/os586/aggbug/60487.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-07-28 10:06 <a href="http://www.blogjava.net/os586/archive/2006/07/28/60487.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Pro Hibernate 3笔记和小结（1）之第一章Hibernate3介绍</title><link>http://www.blogjava.net/os586/archive/2006/07/28/60481.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Fri, 28 Jul 2006 01:55:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/07/28/60481.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/60481.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/07/28/60481.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/60481.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/60481.html</trackback:ping><description><![CDATA[
		<span class="tpc_content">
				<font style="FONT-SIZE: 9pt">/**<br />作者：Willpower<br />来源：Rifoo Technology（</font>
				<a href="http://www.rifoo.com/" target="_blank">http://www.rifoo.com</a>
				<font style="FONT-SIZE: 12px">）<br />时间：2006-05<br />备注：转载请保留以上声明<br />**/<br /><br />今天开始Hibernate3之旅，在Hibernate2的基础上改进了不少，让我们一起借助这本书来学习吧。<br /><br />本书分两个部分，第一部分是Hibernate入门知识（第1到4章），第二部分是Hibernate高级知识（第5到14章）。<br /><br />我们今天来看看第一章的内容：Hibernate 3的介绍。<br /><br />大多数重大的开发项目都会涉及到关系数据库的概念。许多商业应用的核心就是对规则有序的信息进行大规模的存储，比如目录，客户列表，合同资料等。<br /><br />随着互联网的繁荣，对数据库的要求越来越高。在线书店的那些客户们可能自己都不知道，自己每一次的查询操作或者点击某个按钮都会去操作数据库。<br /><br />随着应用程序的需求不段提高，后来出现了标准的EJB规范，EJB规范提供了容器和Bean管理的CMP。但是，这个复杂性很高，而性能却并没有想像中的高。后来，Hibernate的出现给数据的持久化带来了很大的轰动。针对一些数据库持久化解决方案，有用EJB的，有用传统JDBC的，有用Hibernate的。但Hibernate在易用性上显示了突出的优势。<br /><br />这一章我们会提供给大家一个“Hello world”数据库范例。该范例能够通过一个简单的关键字来查找并显示数据库中被保存的一个message信息。下面我们会提供原始JDBC写法和Hibernate写法：<br /><br />Listing 1-1. 这个Main方法会调用我们Hibernate或JDBC的持久化操作<br /></font>
				<div style="FONT-SIZE: 9px; MARGIN-LEFT: 5px">
						<b>CODE:</b>
				</div>
				<div class="quote" id="code1">
						<br />
						<br />public static void main(String[] args) {<br />  if (args.length != 1) {<br />    System.err.println("Nope, enter one message number");<br />  } else {<br />  try {<br />    int messageId = Integer.parseInt(args[0]);<br />    //这一句是调用的方法<br />    [b]Motd motd = getMotd(messageId);[/b]<br />    if (motd != null) {<br />        System.out.println(motd.getMessage());<br />    } else {<br />        System.out.println("No such message");<br />    }<br />  } catch (NumberFormatException e) {<br />    System.err.println("You must enter an integer - " + args[0]<br />        + " won't do.");<br />  } catch (MotdException e) {<br />    System.err.println("Couldn't get the message: " + e);<br />    }<br />  }<br />}<br /></div>
				<div style="FONT-SIZE: 11px; MARGIN-LEFT: 5px">
						<a onclick="CopyCode(document.getElementById('code1'));" href="javascript:">[Copy to clipboard]</a>
				</div>
				<br />
				<br />
				<br />在理想的世界中，我们将很容易的获取任何JAVA对象并将它持久化到数据库。不需要编写额外的特殊代码。也能够保证有良好的性能。对象关系映射（Object Relational Mapping）技术能持久化传统的JAVA对象，而这里的POJO（Plain Old Java Objects）也是一种可重用的JAVA对象，POJO可以是任意的JAVA对象，而不需要Entity Bean那样的命名约束。Hibernate能够帮助我们很轻松地去持久化POJO。<br /><br />下面我们编写POJO部分：<br /><br /><br />Listing 1-2. 本范例中使用到的POJO<br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 5px"><b>CODE:</b></div><div class="quote" id="code2"><br />public class Motd {<br />  protected Motd() {<br />  }<br /><br />  public Motd(int messageId, String message) {<br />    this.messageId = messageId;<br />    this.message = message;<br />  }<br />  public int getId() {<br />    return id;<br />  }<br />  public void setId(int id) {<br />    this.id = id;<br />  }<br />  public String getMessage() {<br />    return message;<br />  }<br />  public void setMessage(String message) {<br />    this.message = message;<br />  }<br />  private int messageId;<br />  private String message;<br />}<br /><br /></div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 5px"><a onclick="CopyCode(document.getElementById('code2'));" href="javascript:">[Copy to clipboard]</a></div><br /><br />下面是从数据库中检索Motd对象的传统JDBC的写法，代码如下：<br /><br /><br />Listing 1-3. 检索POJO<br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 5px"><b>CODE:</b></div><div class="quote" id="code3"><br /><br />public static Motd getMotd(int messageId) throws MotdException {<br />  Connection c = null;<br />  PreparedStatement p = null;<br />  Motd message = null;<br />  try {<br />  Class.forName("org.postgresql.Driver");<br />  c = DriverManager.getConnection(<br />    "jdbc:postgresql://127.0.0.1/hibernate",<br />    "hibernate",<br />    "hibernate");<br />  p = c.prepareStatement(<br />  "select message from motd where id = ?");<br />  p.setInt(1, messageId);<br />  ResultSet rs = p.executeQuery();<br />    if (rs.next()) {<br />        String text = rs.getString(1);<br />        message = new Motd(messageId, text);<br />        if (rs.next()) {<br />          log.warning(<br />          "Multiple messages retrieved for message ID: "<br />          + messageId);<br />          }<br />        }<br />    } catch (Exception e) {<br />    log.log(Level.SEVERE, "Could not acquire message", e);<br />    throw new MotdException(<br />    "Failed to retrieve message from the database.", e);<br />  } finally {<br />    if (p != null) {<br />        try {<br />          p.close();<br />        } catch (SQLException e) {<br />          log.log(Level.WARNING,<br />          "Could not close ostensibly open statement.", e);<br />        }<br />    }<br />    if (c != null) {<br />        try {<br />          c.close();<br />        } catch (SQLException e) {<br />        log.log(Level.WARNING,<br />        "Could not close ostensibly open connection.", e);<br />        }<br />    }<br />  }   <br />return message;<br />}<br /></div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 5px"><a onclick="CopyCode(document.getElementById('code3'));" href="javascript:">[Copy to clipboard]</a></div><br /><br />大家都看到了，这段代码包括数据库连接建立，释放资源等。对于每个查询的方法，都有这样的代码，其实这个显得很冗余。当然了，我们也可以对它进行重构，将这部分代码提取出来，提供一些样本方法。<br /><br /></span>
<img src ="http://www.blogjava.net/os586/aggbug/60481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-07-28 09:55 <a href="http://www.blogjava.net/os586/archive/2006/07/28/60481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate学习笔记find及iterate------之二</title><link>http://www.blogjava.net/os586/archive/2006/07/25/60019.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Tue, 25 Jul 2006 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/07/25/60019.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/60019.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/07/25/60019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/60019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/60019.html</trackback:ping><description><![CDATA[
		<p>在hibernate当中重点比较了find及iterate的使用，主要是他们在查询数据时的优劣势的比较，而由session.find()方法也引申出了query cache这个概念及对find在查询时的劣势的解闷方案。虽然query cache在使用上还是有很多的局限，但是它对提高find的性能起到了很大的作用。<br /><br />在Hibernate2.0当中使用：session.find(),session.iterate(),而hibernate3.0当中使用的是query.find(),query.iterate()来代替。<br /><br />下面我们着重分析一下这两个方法的使用：<br /><br />  1. 如果我们在使用find,iterate进行查询时分别构建他们的HQL，那么我们在控制台输出当中看到iterate()方法所使用的SQL语句的次数要远远超过Find()。<br /><br />  但是，为什么iterate()还存在呢？<br /><br />  2. 当我们在使用find构建HQL后，而同样的查询也让iterate()来执行一次的话(前提是必须使用find()构建的HQL),那么iterate()的执行并不再像前面介绍的那样会比find()方法多执行SQL，而是根本再执行一条SQL。这就是iterate()方法的使用。它使用了Hibernate缓存机制.Find()方法在查询出结果后把查询结果集置入缓存，而iterate()执行的时候先执行一条Select SQL,查询所有符合条件的结果集，接下来iterate()根据查询的id在本地缓存中查找符合条件的结果集，如果有完全符合条件的结果集，则直接以此作为返回结果。如果没有找到再执行相应的SQL,并且把结果纳入缓存当中。以备使用<br /><br /><br /><br />3.缓存机制并不对find()方法起使用。如果你两次执行相同条件的或相近条件的HQL，第二个方法的SQL并不减少。还会照常执行。这就是说缓存机制并不对find()方法起作用。find()对缓存只写不读，而iterate()方法就可以充分利用缓存的优势。<br /><br />4.内存方面的考虑，除了缓存的优势之外，我们还可以利用iterate()与evict()方法来提升查询性能上的优势。<br /><br />     这个问题主要是大数据量所带来的考虑。因为find()方法可以对大数据量的结果集进行缓存，但是如果数据量超大的话，也会带来内存溢出方面的问题。利用iterate(),evict()可以对记录进行逐条处理，将内存消耗保持在可接受的范围之内。<br /><br />  它包括从session中消除对对象，及从sessionFactory当中消除对象。</p>
		<p>5. 对于find()方法在读取缓存问题方面的解决。Query Cache是一个解决方案，不过目前的使用受限比较大。<br /><br />    使用Query Cache的条件是：<br /><br />      A。数据库表结构不变。即未发生过update,insert,delete等操作<br /><br />      B。相同的HSQL的重复执行操作。<br /><br />由于以上两个原因，query Cache的使用上受到了很大 的限制。<br /><br />如果想使用query cache我们需要配置 hibernate.cfg.xml文件：<br /><br />&lt;class ......&gt;<br /><br />   &lt;property nam="hibernate,cache.use_query_cache"&gt;True&lt;/property&gt;<br /><br />&lt;/class&gt;<br /><br /><br /><br />在编码当中使用：Query.setQueryCache(true);即可。<br /><br /></p>
<img src ="http://www.blogjava.net/os586/aggbug/60019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-07-25 16:03 <a href="http://www.blogjava.net/os586/archive/2006/07/25/60019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>POJO与PO的概念理解</title><link>http://www.blogjava.net/os586/archive/2006/07/25/59911.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Tue, 25 Jul 2006 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/07/25/59911.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/59911.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/07/25/59911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/59911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/59911.html</trackback:ping><description><![CDATA[
		<span class="postbody">摘自JAVA视线论坛<br /><br />POJO = pure old java object or plain ordinary java object or what ever. <br /><br />PO = persisent object 持久对象 <br /><br />就是说在一些Object/Relation Mapping工具中，能够做到维护数据库表记录的persisent object完全是一个符合Java Bean规范的纯Java对象，没有增加别的属性和方法。全都是这样子的： <br /><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> User <span style="COLOR: #000000">{</span><br />  <span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">private</span> long id; <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" ?="">public</span><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">void</span> setId<span style="COLOR: #000000">(</span>long id<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />this.<span style="COLOR: #000000">id</span> = id; <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> setName<span style="COLOR: #000000">(</span><span style="COLOR: #aaaadd" ?="">String</span> name<span style="COLOR: #000000">)</span><span style="COLOR: #000000">{</span><br />this.<span style="COLOR: #000000">name</span>=name; <br /><span style="COLOR: #000000">}</span><br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span> long getId<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> id; <br /><span style="COLOR: #000000">}</span>  <br /><span style="FONT-WEIGHT: bold; COLOR: #990066" ?="">public</span><span style="COLOR: #aaaadd" ?="">String</span> getName<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> name; <br /><span style="COLOR: #000000">}</span><br /><span style="COLOR: #000000">}</span> </div>
										<br />
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />--------------------------------------------------------------------------- <br />首先要区别持久对象和POJO。 <br /><br />持久对象实际上必须对应数据库中的entity，所以和POJO有所区别。比如说POJO是由new创建，由GC回收。但是持久对象是insert数据库创建，由数据库delete删除的。基本上持久对象生命周期和数据库密切相关。另外持久对象往往只能存在一个数据库Connection之中，Connnection关闭以后，持久对象就不存在了，而POJO只要不被GC回收，总是存在的。 <br /><br />由于存在诸多差别，因此持久对象PO(Persistent Object)在代码上肯定和POJO不同，起码PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。而ORM追求的目标就是要PO在使用上尽量和POJO一致，对于程序员来说，他们可以把PO当做POJO来用，而感觉不到PO的存在。 <br /><br />JDO的实现方法是这样的： <br />1、编写POJO <br />2、编译POJO <br />3、使用JDO的一个专门工具，叫做Enhancer，一般是一个命令行程序，手工运行，或者在ant脚本里面运行，对POJO的class文件处理一下，把POJO替换成同名的PO。 <br />4、在运行期运行的实际上是PO，而不是POJO。 <br /><br />该方法有点类似于JSP，JSP也是在编译期被转换成Servlet来运行的，在运行期实际上运行的是Servlet，而不是JSP。 <br /><br />Hibernate的实现方法比较先进： <br />1、编写POJO <br />2、编译POJO <br />3、直接运行，在运行期，由Hibernate的CGLIB动态把POJO转换为PO。 <br /><br />由此可以看出Hibernate是在运行期把POJO的字节码转换为PO的，而JDO是在编译期转换的。一般认为JDO的方式效率会稍高，毕竟是编译期转换嘛。但是Hibernate的作者Gavin King说CGLIB的效率非常之高，运行期的PO的字节码生成速度非常之快，效率损失几乎可以忽略不计。 <br /><br />实际上运行期生成PO的好处非常大，这样对于程序员来说，是无法接触到PO的，PO对他们来说完全透明。可以更加自由的以POJO的概念操纵PO。另外由于是运行期生成PO，所以可以支持增量编译，增量调试。而JDO则无法做到这一点。实际上已经有很多人在抱怨JDO的编译期Enhancer问题了，而据说JBossDO将采用运行期生成PO字节码，而不采用编译期生成PO字节码。 <br /><br />另外一个相关的问题是，不同的JDO产品的Enhancer生成的PO字节码可能会有所不同，可能会影响在JDO产品之间的可移植性，这一点有点类似EJB的可移植性难题。 <br /><br />----------------------------------------------------------------------------------- <br />由这个问题另外引出一个JDO的缺陷。 <br /><br />由于JDO的PO状态管理方式，所以当你在程序里面get/set的时候，实际上不是从PO的实例中取values，而是从JDO StateManager中取出来，所以一旦PM关闭，PO就不能进行存取了。 <br /><br />在JDO中，也可以通过一些办法使得PO可以在PM外面使用，比如说定义PO是transient的，但是该PO在PM关闭后就没有PO identity了。无法进行跨PM的状态管理。 <br /><br />而Hibernate是从PO实例中取values的，所以即使Session关闭，也一样可以get/set，可以进行跨Session的状态管理。 <br /><br />在分多层的应用中，由于持久层和业务层和web层都是分开的，此时Hibernate的PO完全可以当做一个POJO来用，也就是当做一个VO，在各层间自由传递，而不用去管Session是开还是关。如果你把这个POJO序列化的话，甚至可以用在分布式环境中。（不适合lazy loading的情况） <br /><br />但是JDO的PO在PM关闭后就不能再用了，所以必须在PM关闭前把PO拷贝一份VO，把VO传递给业务层和web层使用。在非分布式环境中，也可以使用ThreadLocal模式确保PM始终是打开状态，来避免每次必须进行PO到VO的拷贝操作。但是不管怎么说，这总是权宜之计，不如Hibernate的功能强。</span>
<img src ="http://www.blogjava.net/os586/aggbug/59911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-07-25 09:08 <a href="http://www.blogjava.net/os586/archive/2006/07/25/59911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse3.1 安装xmlBuddy2.0.72的问题解决</title><link>http://www.blogjava.net/os586/archive/2006/07/20/59237.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Thu, 20 Jul 2006 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/07/20/59237.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/59237.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/07/20/59237.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/59237.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/59237.html</trackback:ping><description><![CDATA[
		<p>xmlBuddy2.0.72是支持Eclipse3.1版的。但是在下载了xmlbuddy后解压后把解压后的文件复制到Eclipse下的plugins下却不显示。<br /><br />一直认为xmlBuddy2.0.72可能不支持3.1的Eclipse，后来上网上看资料后确认是支持的。<br /><br />但是启动了N遍eclipse也不能找到xmlbuddy的两个图标。<br /><br />后来，看见网上也有相似的问题发生。<br /><br />解决的办法是在eclipse的启动参数后面加入 -clean后就可。</p>
<img src ="http://www.blogjava.net/os586/aggbug/59237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-07-20 17:16 <a href="http://www.blogjava.net/os586/archive/2006/07/20/59237.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从今儿开始学习Hibernate</title><link>http://www.blogjava.net/os586/archive/2006/06/26/55059.html</link><dc:creator>水煮三国</dc:creator><author>水煮三国</author><pubDate>Mon, 26 Jun 2006 01:02:00 GMT</pubDate><guid>http://www.blogjava.net/os586/archive/2006/06/26/55059.html</guid><wfw:comment>http://www.blogjava.net/os586/comments/55059.html</wfw:comment><comments>http://www.blogjava.net/os586/archive/2006/06/26/55059.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/os586/comments/commentRss/55059.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/os586/services/trackbacks/55059.html</trackback:ping><description><![CDATA[
		<p>对Java的理解还不是太深,现在看到那么多的开源工具,心里很痒.<br /><br />大家对Struts,Spring,Hibernate这些开源工具是怎样理解的.<br /><br />我对Struts还是了解一些,但是对Spring,Hibernate还不是很了解.<br /><br />如果有一起学习这些工具的网友们,<br /><br />我们可以在这里交流学习</p>
<img src ="http://www.blogjava.net/os586/aggbug/55059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/os586/" target="_blank">水煮三国</a> 2006-06-26 09:02 <a href="http://www.blogjava.net/os586/archive/2006/06/26/55059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>