﻿<?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-风人园-文章分类-DAO</title><link>http://www.blogjava.net/wuxufeng8080/category/18455.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 07 Mar 2007 16:27:02 GMT</lastBuildDate><pubDate>Wed, 07 Mar 2007 16:27:02 GMT</pubDate><ttl>60</ttl><item><title>Don’t repeat the DAO!</title><link>http://www.blogjava.net/wuxufeng8080/articles/101870.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Mon, 05 Mar 2007 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/101870.html</guid><description><![CDATA[
		<p>译者：Nicholas @ Nirvana Studio<br />原文地址：http://www-128.ibm.com/developerworks/java/library/j-genericdao.html </p>
		<p>使用Hibernate和Spring AOP购建一个范型类型安全的DAO<br />2006年五月12日<br /></p>
		<blockquote>在采用了Java 5的范型之后，要实现一个基于范型类型安全的数据访问对象（DAO）就变得切实可行了。在这篇文章里，系统架构师Per Mellqvist展示了一个基于Hibernate的范型DAO实现。然后将介绍如何使用Spring AOP的introduction为一个类增加一个类型安全的接口以便于执行查询。</blockquote>
		<p>对于大多数开发者来说，在系统中为每一个DAO编写几乎一样的代码已经成为了一种习惯。同时大家也都认可这种重复就是“代码的味道”，我们中的大多数已经习惯如此。当然也有另外的办法。你可以使用很多ORM工具来避免代码的重复编写。举个例子，用Hibernate，你可以简单的使用session操作直接控制你的持久化领域对象。这种方式的负面影响就是丢失了类型安全。 </p>
		<p>为什么你的数据访问代码需要一个类型安全的接口？我认为它减少了编程错误，提高了生产率，尤其是在使用现代高级IDE的时候。首先，一个类型安全的接口清晰的制定了哪些领域对象具有持久化功能。其次，它消除了类型转换带来的潜在问题。最后，它平衡了IDE的自动完成功能。使用自动完成功能是最快的方式来记住对于适当的领域类哪些查询是可用的。 </p>
		<p>在这篇文章里，我将展示给大家如何避免一次次地重复编写DAO代码，但同时还收益于类型安全的接口。事实上，所有内需要编写的是为新的DAO编写一个Hibernate映射文件，一个POJO的Java接口，并且10行Spring配置文件。 
</p>
		<h2>DAO实现</h2>
		<p>DAO模式对于任何Java开发人员来说都是耳熟能详的。这个模式的实现相当多，所以让我们仔细推敲一下我这篇文章里面对于DAO实现的一些假设： 
</p>
		<ul>
				<li>所有系统中的数据库访问都是通过DAO来完成封装 
</li>
				<li>每一个DAO实例对一个主要的领域对象或者实体负责。如果一个领域对象具有独立的生命周期，那么它需要具有自己的DAO。 
</li>
				<li>DAO具有CRUD操作 
</li>
				<li>DAO可以允许基于criteria方式的查询而不仅仅是通过主键查询。我将这些成为finder方法或者finders。这个finder的返回值通常是DAO所负责的领域对象的集合。 </li>
		</ul>
		<h2>范型DAO接口</h2>
		<p>范型DAO的基础就是CRUD操作。下面的接口定义了范型DAO的方法： 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">interface</span> GenericDao &lt;T, PK <span style="FONT-WEIGHT: bold; COLOR: #000000">extends</span> Serializable&gt; <span style="COLOR: #66cc66">{</span>
 
    <span style="COLOR: #808080; FONT-STYLE: italic">/** Persist the newInstance object into database */</span>
    PK create<span style="COLOR: #66cc66">(</span>T newInstance<span style="COLOR: #66cc66">)</span>;
 
    <span style="COLOR: #808080; FONT-STYLE: italic">/** Retrieve an object that was previously persisted to the database using
     *   the indicated id as primary key
     */</span>
    T read<span style="COLOR: #66cc66">(</span>PK id<span style="COLOR: #66cc66">)</span>;
 
    <span style="COLOR: #808080; FONT-STYLE: italic">/** Save changes made to a persistent object.  */</span><span style="COLOR: #993333">void</span> update<span style="COLOR: #66cc66">(</span>T transientObject<span style="COLOR: #66cc66">)</span>;
 
    <span style="COLOR: #808080; FONT-STYLE: italic">/** Remove an object from persistent storage in the database */</span><span style="COLOR: #993333">void</span> delete<span style="COLOR: #66cc66">(</span>T persistentObject<span style="COLOR: #66cc66">)</span>;
<span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<h3>实现这个接口</h3>
		<p>使用Hibernate实现上面的接口是非常简单的。也就是调用一下Hibernate的方法和增加一些类型转换。Spring负责session和transaction管理。 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">class</span> GenericDaoHibernateImpl &lt;T, PK <span style="FONT-WEIGHT: bold; COLOR: #000000">extends</span> Serializable&gt;
    <span style="FONT-WEIGHT: bold; COLOR: #000000">implements</span> GenericDao&lt;T, PK&gt;, FinderExecutor <span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">private</span> Class&lt;T&gt; type;
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span> GenericDaoHibernateImpl<span style="COLOR: #66cc66">(</span>Class&lt;T&gt; type<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">this</span>.<span style="COLOR: #006600">type</span> = type;
    <span style="COLOR: #66cc66">}</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span> PK create<span style="COLOR: #66cc66">(</span>T o<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span><span style="COLOR: #66cc66">(</span>PK<span style="COLOR: #66cc66">)</span> getSession<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">save</span><span style="COLOR: #66cc66">(</span>o<span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span> T read<span style="COLOR: #66cc66">(</span>PK id<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span><span style="COLOR: #66cc66">(</span>T<span style="COLOR: #66cc66">)</span> getSession<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">get</span><span style="COLOR: #66cc66">(</span>type, id<span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><span style="COLOR: #993333">void</span> update<span style="COLOR: #66cc66">(</span>T o<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span>
        getSession<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">update</span><span style="COLOR: #66cc66">(</span>o<span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><span style="COLOR: #993333">void</span> delete<span style="COLOR: #66cc66">(</span>T o<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span>
        getSession<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">delete</span><span style="COLOR: #66cc66">(</span>o<span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span>
 
    <span style="COLOR: #808080; FONT-STYLE: italic">// Not showing implementations of getSession() and setSessionFactory()</span><span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<h3>Spring 配置</h3>
		<p>最后，Spring配置，我创建了一个GenericDaoHibernateImpl的实例。GenericDaoHibernateImpl的构造器必须被告知领域对象的类型，这样DAO实例才能为之负责。这个同样需要Hibernate运行时知道这个对象的类型。下面的代码中，我将领域类Person传递给构造器并且将Hibernate的session工厂作为一个参数用来实例化DAO： 
</p>
		<blockquote>
				<pre class="xml">
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span>
								<span style="COLOR: #000066">id</span>=<span style="COLOR: #ff0000">"personDao"</span><span style="COLOR: #000066">class</span>=<span style="COLOR: #ff0000">"genericdao.impl.GenericDaoHibernateImpl"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;constructor-arg<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						</span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						</span>genericdaotest.domain.Person<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/constructor-arg<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span><span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"sessionFactory"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;ref</span><span style="COLOR: #000066">bean</span>=<span style="COLOR: #ff0000">"sessionFactory"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/property<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/bean<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span></pre>
		</blockquote>
		<h2>可用的范型DAO</h2>
		<p>我还没有全部完成，但我现在已经有了一个可供作的代码。下面的代码展示了范型DAO如何使用： 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="COLOR: #993333">void</span> someMethodCreatingAPerson<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span>
    ...
    <span style="COLOR: #006600">GenericDao</span> dao = <span style="COLOR: #66cc66">(</span>GenericDao<span style="COLOR: #66cc66">)</span>
     beanFactory.<span style="COLOR: #006600">getBean</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"personDao"</span><span style="COLOR: #66cc66">)</span>; <span style="COLOR: #808080; FONT-STYLE: italic">// This should normally be injected</span>
 
    Person p = <span style="FONT-WEIGHT: bold; COLOR: #000000">new</span> Person<span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"Per"</span>, <span style="COLOR: #cc66cc">90</span><span style="COLOR: #66cc66">)</span>;
    dao.<span style="COLOR: #006600">create</span><span style="COLOR: #66cc66">(</span>p<span style="COLOR: #66cc66">)</span>;
<span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<p>这时候，我有一个范型DAO有能力进行类型安全的CRUD操作。同时也有理由编写GenericDaoHibernateImpl的子类来为每个领域对象增加查询功能。但是这篇文章的主旨在于展示如何完成这项功能而不是为每个查询编写明确的代码，然而，我将会使用多个工具来介绍DAO的查询，这就是Spring AOP和Hibernate命名查询。 
</p>
		<h2>Spring AOP介绍</h2>
		<p>你可以使用Spring AOP提供的introduction功能将一个现存的对象包装到一个代理里面来增加新的功能，定义它需要实现的新接口，并且将之前所有不支持的方法委派到一个处理机。在我的DAO实现里面，我用introduction将一定数量的finder方法增加到现存的范型DAO类里面。因为finder方法针对特定的领域对象，所以它们被应用到表明接口的范型DAO中。 
</p>
		<blockquote>
				<pre class="xml">
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span>
								<span style="COLOR: #000066">id</span>=<span style="COLOR: #ff0000">"finderIntroductionAdvisor"</span><span style="COLOR: #000066">class</span>=<span style="COLOR: #ff0000">"genericdao.impl.FinderIntroductionAdvisor"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span>
 
<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span><span style="COLOR: #000066">id</span>=<span style="COLOR: #ff0000">"abstractDaoTarget"</span><span style="COLOR: #000066">class</span>=<span style="COLOR: #ff0000">"genericdao.impl.GenericDaoHibernateImpl"</span><span style="COLOR: #000066">abstract</span>=<span style="COLOR: #ff0000">"true"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span><span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"sessionFactory"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;ref</span><span style="COLOR: #000066">bean</span>=<span style="COLOR: #ff0000">"sessionFactory"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/property<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/bean<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span>
 
<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span><span style="COLOR: #000066">id</span>=<span style="COLOR: #ff0000">"abstractDao"</span><span style="COLOR: #000066">class</span>=<span style="COLOR: #ff0000">"org.springframework.aop.framework.ProxyFactoryBean"</span><span style="COLOR: #000066">abstract</span>=<span style="COLOR: #ff0000">"true"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span><span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"interceptorNames"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;list<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span>finderIntroductionAdvisor<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/list<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/property<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/bean<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span></pre>
		</blockquote>
		<p>在上面的配置中，我定义了三个Spring bean，第一个bean，FinderIntroductionAdvisor，处理那些introduce到DAO中但是不属于GenericDaoHibernateImpl类的方法。一会我再介绍Advisor bean的详细情况。 </p>
		<p>第二个bean定义为“abstract”。在Spring中，这个bean可以被其他bean重用但是它自己不会被实例化。不同于抽象属性，bean的定义简单的指出了我需要一个GenericDaoHibernateImpl的实例同时需要一个SessionFactory的引用。注意GenericDaoHibernateImpl类只定义了一个构造器接受领域类作为参数。因为这个bean是抽象的，我可以无限次的重用并且设定合适的领域类。 </p>
		<p>最后，第三个，也是最有意思的是bean将GenericDaoHibernateImpl的实例包装进了一个代理，给予了它执行finder方法的能力。这个bean定义同样是抽象的并且没有指定任何接口。这个接口不同于任何具体的实例。 
</p>
		<h3>扩展通用DAO</h3>
		<p>每个DAO的接口，都是基于GenericDAO接口的。我需要将为特定的领域类适配接口并且将其扩展包含我的finder方法。 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">interface</span> PersonDao <span style="FONT-WEIGHT: bold; COLOR: #000000">extends</span> GenericDao&lt;Person, Long&gt; <span style="COLOR: #66cc66">{</span>
    List&lt;Person&gt; findByName<span style="COLOR: #66cc66">(</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">String</span></a> name<span style="COLOR: #66cc66">)</span>;
<span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<p>上面的代码清晰的展示了通过用户名查找Person对象列表。所需的Java实现类不需要包含任何的更新操作，因为这些已经包含在了通用DAO里。 
</p>
		<h3>配置PersonDao</h3>
		<p>因为Spring配置依赖之前的那些抽象bean，所以它变得很紧凑。我需要指定DAO负责的领域类，并且我需要告诉Spring我这个DAO需要实现的接口。 
</p>
		<blockquote>
				<pre class="xml">
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span>
								<span style="COLOR: #000066">id</span>=<span style="COLOR: #ff0000">"personDao"</span><span style="COLOR: #000066">parent</span>=<span style="COLOR: #ff0000">"abstractDao"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span>
								<span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"proxyInterfaces"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						</span>genericdaotest.dao.PersonDao<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/property<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span><span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"target"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;bean</span><span style="COLOR: #000066">parent</span>=<span style="COLOR: #ff0000">"abstractDaoTarget"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;constructor-arg<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span>genericdaotest.domain.Person<span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/value<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/constructor-arg<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/bean<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/property<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/bean<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span></pre>
		</blockquote>
		<p>你可以这样使用： 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="COLOR: #993333">void</span> someMethodCreatingAPerson<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span>
    ...
    <span style="COLOR: #006600">PersonDao</span> dao = <span style="COLOR: #66cc66">(</span>PersonDao<span style="COLOR: #66cc66">)</span>
     beanFactory.<span style="COLOR: #006600">getBean</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"personDao"</span><span style="COLOR: #66cc66">)</span>; <span style="COLOR: #808080; FONT-STYLE: italic">// This should normally be injected</span>
 
    Person p = <span style="FONT-WEIGHT: bold; COLOR: #000000">new</span> Person<span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"Per"</span>, <span style="COLOR: #cc66cc">90</span><span style="COLOR: #66cc66">)</span>;
    dao.<span style="COLOR: #006600">create</span><span style="COLOR: #66cc66">(</span>p<span style="COLOR: #66cc66">)</span>;
 
    List&lt;Person&gt; result = dao.<span style="COLOR: #006600">findByName</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"Per"</span><span style="COLOR: #66cc66">)</span>; <span style="COLOR: #808080; FONT-STYLE: italic">// Runtime exception</span><span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<p>上面的代码是使用类型安全接口PersonDao的一种正确途径，但是DAO的实现并没有完成。当调用findByName()的时候导致了一个运行时异常。这个问题是我还没有findByName()。剩下的工作就是指定查询语句。要完成这个，我使用Hibernate命名查询。 
</p>
		<h3>Hibernate命名查询</h3>
		<p>使用Hibernate，你可以定义任何HQL查询在映射文件里，并且给它一个名字。你可以在之后的代码里面方便的通过名字引用这个查询。这么做的一个优点就是能够在部署的时候调节查询而不需要改变代码。正如你一会将看到的，另一个好处就是实现一个“完整”的DAO而不需要编写任何Java实现代码。 
</p>
		<blockquote>
				<pre class="xml">
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;hibernate-mapping</span>
								<span style="COLOR: #000066">package</span>=<span style="COLOR: #ff0000">"genericdaotest.domain"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;class</span>
								<span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"Person"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;id</span>
								<span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"id"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;generator</span>
								<span style="COLOR: #000066">class</span>=<span style="COLOR: #ff0000">"native"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;/id<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						</span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span>
								<span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"name"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;property</span>
								<span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"weight"</span><span style="FONT-WEIGHT: bold; COLOR: black">/&gt;</span></span>
						<span style="COLOR: #009900">
								<span style="FONT-WEIGHT: bold; COLOR: black">&lt;/class<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span>
						</span>
 
     <span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;query</span><span style="COLOR: #000066">name</span>=<span style="COLOR: #ff0000">"Person.findByName"</span><span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span><span style="COLOR: #339933">&lt;![CDATA[select p from Person p where p.name = ? ]]&gt;</span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/query<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span><span style="COLOR: #009900"><span style="FONT-WEIGHT: bold; COLOR: black">&lt;/hibernate-mapping<span style="FONT-WEIGHT: bold; COLOR: black">&gt;</span></span></span></pre>
		</blockquote>
		<p>上面的代码定义了领域类Person的Hibernate映射文件，有两个属性：name和weight。Person是一个具有上面属性的简单的POJO。这个文件同时包含了一个查询，通过提供的name属性从数据库查找Person实例。Hibernate为命名查询提供了不真实的命名空间功能。为了便于讨论，我将所有的查询名字的前缀变成领域类的的名称。在现实场景中，使用完整的类名，包含包名，是一个更好的主意。 
</p>
		<h2>总览</h2>
		<p>你已经看到了为任何领域对象创建并配置DAO的所需步骤了。这三个简单的步骤就是： 
</p>
		<ol>
				<li>定义一个接口继承GenericDao并且包含任何所需的finder方法 
</li>
				<li>在映射文件中为每个领域类的finder方法增加一个命名查询。 
</li>
				<li>为DAO增加10行Spring配置 </li>
		</ol>
		<h2>可重用的DAO类</h2>
		<p>Spring advisor和interceptor的功能比较琐碎，事实上他们的工作都引用回了GenericDaoHibernateImpl类。所有带有“find”开头的方法都被传递给DAO的单一方法executeFinder()。 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span>
						<span style="FONT-WEIGHT: bold; COLOR: #000000">class</span> FinderIntroductionAdvisor <span style="FONT-WEIGHT: bold; COLOR: #000000">extends</span> DefaultIntroductionAdvisor <span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">public</span> FinderIntroductionAdvisor<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">super</span><span style="COLOR: #66cc66">(</span><span style="FONT-WEIGHT: bold; COLOR: #000000">new</span> FinderIntroductionInterceptor<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span><span style="COLOR: #66cc66">}</span>
 
<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><span style="FONT-WEIGHT: bold; COLOR: #000000">class</span> FinderIntroductionInterceptor <span style="FONT-WEIGHT: bold; COLOR: #000000">implements</span> IntroductionInterceptor <span style="COLOR: #66cc66">{</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><a href="http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+Object"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Object</span></a> invoke<span style="COLOR: #66cc66">(</span>MethodInvocation methodInvocation<span style="COLOR: #66cc66">)</span><span style="FONT-WEIGHT: bold; COLOR: #000000">throws</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Throwable</span></a><span style="COLOR: #66cc66">{</span>
 
        FinderExecutor genericDao = <span style="COLOR: #66cc66">(</span>FinderExecutor<span style="COLOR: #66cc66">)</span> methodInvocation.<span style="COLOR: #006600">getThis</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
 
        <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">String</span></a> methodName = methodInvocation.<span style="COLOR: #006600">getMethod</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">getName</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
        <span style="COLOR: #b1b100">if</span><span style="COLOR: #66cc66">(</span>methodName.<span style="COLOR: #006600">startsWith</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #ff0000">"find"</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><a href="http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+Object"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Object</span></a><span style="COLOR: #66cc66">[</span><span style="COLOR: #66cc66">]</span> arguments = methodInvocation.<span style="COLOR: #006600">getArguments</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
            <span style="FONT-WEIGHT: bold; COLOR: #000000">return</span> genericDao.<span style="COLOR: #006600">executeFinder</span><span style="COLOR: #66cc66">(</span>methodInvocation.<span style="COLOR: #006600">getMethod</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>, arguments<span style="COLOR: #66cc66">)</span>;
        <span style="COLOR: #66cc66">}</span><span style="COLOR: #b1b100">else</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span> methodInvocation.<span style="COLOR: #006600">proceed</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
        <span style="COLOR: #66cc66">}</span><span style="COLOR: #66cc66">}</span>
 
    <span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><span style="COLOR: #993333">boolean</span> implementsInterface<span style="COLOR: #66cc66">(</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Class</span></a> intf<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span> intf.<span style="COLOR: #006600">isInterface</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span> &amp;&amp; FinderExecutor.<span style="FONT-WEIGHT: bold; COLOR: #000000">class</span>.<span style="COLOR: #006600">isAssignableFrom</span><span style="COLOR: #66cc66">(</span>intf<span style="COLOR: #66cc66">)</span>;
    <span style="COLOR: #66cc66">}</span><span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<h3>executeFinder() 方法</h3>
		<p>上面的代码唯一缺的就是executeFinder的实现。这个代码观察被调用的类的名字和方法，并且将他们与Hibernate的查询名相匹配。你可以使用一个FinderNamingStrategy来激活其他方式的命名查询。默认的实现查找一个名为“ClassName.methodName”的查询，ClassName是除包名之外的类名。 
</p>
		<blockquote>
				<pre class="java5">
						<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span> List&lt;T&gt; executeFinder<span style="COLOR: #66cc66">(</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Method</span></a> method, <span style="FONT-WEIGHT: bold; COLOR: #000000">final</span><a href="http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+Object"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Object</span></a><span style="COLOR: #66cc66">[</span><span style="COLOR: #66cc66">]</span> queryArgs<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">final</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">String</span></a> queryName = queryNameFromMethod<span style="COLOR: #66cc66">(</span>method<span style="COLOR: #66cc66">)</span>;
     <span style="FONT-WEIGHT: bold; COLOR: #000000">final</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/management/Query.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Query</span></a> namedQuery = getSession<span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>.<span style="COLOR: #006600">getNamedQuery</span><span style="COLOR: #66cc66">(</span>queryName<span style="COLOR: #66cc66">)</span>;
     <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">String</span></a><span style="COLOR: #66cc66">[</span><span style="COLOR: #66cc66">]</span> namedParameters = namedQuery.<span style="COLOR: #006600">getNamedParameters</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
     <span style="COLOR: #b1b100">for</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #993333">int</span> i = <span style="COLOR: #cc66cc">0</span>; i &lt; queryArgs.<span style="COLOR: #006600">length</span>; i++<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><a href="http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+Object"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Object</span></a> arg = queryArgs<span style="COLOR: #66cc66">[</span>i<span style="COLOR: #66cc66">]</span>;
             <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Type.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Type</span></a> argType =  namedQuery.<span style="COLOR: #006600">setParameter</span><span style="COLOR: #66cc66">(</span>i, arg<span style="COLOR: #66cc66">)</span>;
      <span style="COLOR: #66cc66">}</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span><span style="COLOR: #66cc66">(</span>List&lt;T&gt;<span style="COLOR: #66cc66">)</span> namedQuery.<span style="COLOR: #006600">list</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
<span style="COLOR: #66cc66">}</span>
 
<span style="FONT-WEIGHT: bold; COLOR: #000000">public</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">String</span></a> queryNameFromMethod<span style="COLOR: #66cc66">(</span><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Method.html"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Method</span></a> finderMethod<span style="COLOR: #66cc66">)</span><span style="COLOR: #66cc66">{</span><span style="FONT-WEIGHT: bold; COLOR: #000000">return</span> type.<span style="COLOR: #006600">getSimpleName</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span> + <span style="COLOR: #ff0000">"."</span> + finderMethod.<span style="COLOR: #006600">getName</span><span style="COLOR: #66cc66">(</span><span style="COLOR: #66cc66">)</span>;
<span style="COLOR: #66cc66">}</span></pre>
		</blockquote>
		<h2>总结</h2>
		<p>在Java 5之前，Java语言并不支持代码同时具有类型安全和范性的特性；你不得不二者选一。在这篇文章里，你可以看到使用Java 5范型支持并且结合Spring和Hibernate（和AOP）一起来提高生产力。一个范型类型安全的DAO类非常容易编写，所有你需要做的就是一个接口，一些命名查询，并且10行Spring配置，并且可以极大的减少错误，同时节省时间。 </p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/101870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-03-05 11:51 <a href="http://www.blogjava.net/wuxufeng8080/articles/101870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring DAO 测试</title><link>http://www.blogjava.net/wuxufeng8080/articles/94597.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Thu, 18 Jan 2007 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/94597.html</guid><description><![CDATA[今天我将展示一下我是如何在实际中对dao进行单元测试的<br />首先我们来确认一下dao需要什么样的环境，我的dao是用Spring+hibernate来构建的，而对应的数据源是oracle9。所以要进行dao的测试我需要从Spring的连接oracle的context中获取dao的实例出来，这里我使用的是spring-mock<br />spring-mock使用比较简单的，只需要设置spring的配置文件路径就可以获得上下文了<br />这里需要注意的是这个spring上下文是ClassPathApplicationContext,而我们在web环境中经常遇到的是WebApplicationContext<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_0_69_Open_Image" onclick="this.style.display='none'; Codehighlighter1_0_69_Open_Text.style.display='none'; Codehighlighter1_0_69_Closed_Image.style.display='inline'; Codehighlighter1_0_69_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_0_69_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_69_Closed_Text.style.display='none'; Codehighlighter1_0_69_Open_Image.style.display='inline'; Codehighlighter1_0_69_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span id="Codehighlighter1_0_69_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/** */</span><span id="Codehighlighter1_0_69_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> * $Id:$<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> *<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /> * Copyright 2005 easou, Inc. All Rights Reserved.<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000"> test.spring.common;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> test.PathConfig;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> BaseSpringTestCase </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_301_550_Open_Image" onclick="this.style.display='none'; Codehighlighter1_301_550_Open_Text.style.display='none'; Codehighlighter1_301_550_Closed_Image.style.display='inline'; Codehighlighter1_301_550_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_301_550_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_301_550_Closed_Text.style.display='none'; Codehighlighter1_301_550_Open_Image.style.display='inline'; Codehighlighter1_301_550_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />        AbstractTransactionalDataSourceSpringContextTests </span><span id="Codehighlighter1_301_550_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_301_550_Open_Text"><span style="COLOR: #000000">{<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    @Override<br /><img id="Codehighlighter1_359_424_Open_Image" onclick="this.style.display='none'; Codehighlighter1_359_424_Open_Text.style.display='none'; Codehighlighter1_359_424_Closed_Image.style.display='inline'; Codehighlighter1_359_424_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_359_424_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_359_424_Closed_Text.style.display='none'; Codehighlighter1_359_424_Open_Image.style.display='inline'; Codehighlighter1_359_424_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000"> String[] getConfigLocations() </span><span id="Codehighlighter1_359_424_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_359_424_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        String[] config </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> PathConfig.springxml;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> config;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /><img id="Codehighlighter1_456_547_Open_Image" onclick="this.style.display='none'; Codehighlighter1_456_547_Open_Text.style.display='none'; Codehighlighter1_456_547_Closed_Image.style.display='inline'; Codehighlighter1_456_547_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_456_547_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_456_547_Closed_Text.style.display='none'; Codehighlighter1_456_547_Open_Image.style.display='inline'; Codehighlighter1_456_547_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testConfig() </span><span id="Codehighlighter1_456_547_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_456_547_Open_Text"><span style="COLOR: #000000">{        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">spring-mock context has bean init()</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.applicationContext);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>这里testConfig是用来检查你spring配置的加载是否正确的<br /><br />下面给出一个DAO的简单查询方法 
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_56_178_Open_Image" onclick="this.style.display='none'; Codehighlighter1_56_178_Open_Text.style.display='none'; Codehighlighter1_56_178_Closed_Image.style.display='inline'; Codehighlighter1_56_178_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_56_178_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_178_Closed_Text.style.display='none'; Codehighlighter1_56_178_Open_Image.style.display='inline'; Codehighlighter1_56_178_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> List getHomepageAreasByChannelId(</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> channelId) </span><span id="Codehighlighter1_56_178_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_56_178_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.executeHQL(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> from CsHomepageArea  h where h.csChannel.id='</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> channelId </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">' order by h.theOrder</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div><p><br />上面的方法指示根据一个id取列表出来，而我们要测试的目标有（其实也就是我们这个方法要实现的目标）：<br />1、给出正确的id是否能否返回正确的结果<br />2、返回的结果集能够根据hibernate配置文件而得到我们期望的结果集（比如说对子集的lazy读取）<br />3、返回的结果集是否按照你所期望的排序<br />4、给出错误的id是否在获取数据时会出错<br />根据上面的测试目标我们就很容易的得到下面的测试方法了<br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_46_780_Open_Image" onclick="this.style.display='none'; Codehighlighter1_46_780_Open_Text.style.display='none'; Codehighlighter1_46_780_Closed_Image.style.display='inline'; Codehighlighter1_46_780_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_46_780_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_46_780_Closed_Text.style.display='none'; Codehighlighter1_46_780_Open_Image.style.display='inline'; Codehighlighter1_46_780_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testGetHomepageAreasByChannelId() </span><span id="Codehighlighter1_46_780_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_46_780_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        List list </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> channelDAO.getHomepageAreasByChannelId(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage list is not null</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, list);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsHomepageArea homepage </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (CsHomepageArea) list.get(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage'name is not null</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, homepage.getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage'channel has been lazy</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, homepage.getCsChannel()<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                .getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage'column has been lazy</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, homepage.getCsColumn()<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                .getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage'subject has been lazy</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, homepage<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                .getCsSubjects().iterator().next().getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsSubject subject </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (CsSubject) homepage.getCsSubjects().iterator()<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                .next();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">homepage'subject'keyword has been lazy</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, subject<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                .getCsSubjectKeywords().iterator().next().getName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div><p><strong>对于DAO层的查询方法，我们测试的就是判断返回的数据是否是我们需要的</strong></p><p>下面这个方法是DAO的增改方法，和删除方法<br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_43_96_Open_Image" onclick="this.style.display='none'; Codehighlighter1_43_96_Open_Text.style.display='none'; Codehighlighter1_43_96_Closed_Image.style.display='inline'; Codehighlighter1_43_96_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_43_96_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_43_96_Closed_Text.style.display='none'; Codehighlighter1_43_96_Open_Image.style.display='inline'; Codehighlighter1_43_96_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> saveComment(CsComment comment) </span><span id="Codehighlighter1_43_96_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_43_96_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        getHibernateTemplate().saveOrUpdate(comment);        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_144_193_Open_Image" onclick="this.style.display='none'; Codehighlighter1_144_193_Open_Text.style.display='none'; Codehighlighter1_144_193_Closed_Image.style.display='inline'; Codehighlighter1_144_193_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_144_193_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_144_193_Closed_Text.style.display='none'; Codehighlighter1_144_193_Open_Image.style.display='inline'; Codehighlighter1_144_193_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> deleteComment(CsComment comment) </span><span id="Codehighlighter1_144_193_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_144_193_Open_Text"><span style="COLOR: #000000">{        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        getHibernateTemplate().delete(comment);        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div><p> </p><p>对于这种无返回值得方法我们主要测试的是：<br />1、对于正确的数据是否能够正确的存入数据库或者从数据库删除<br />2、对于错误的数据操作能够有错误信息（如主键重复）<br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_29_309_Open_Image" onclick="this.style.display='none'; Codehighlighter1_29_309_Open_Text.style.display='none'; Codehighlighter1_29_309_Closed_Image.style.display='inline'; Codehighlighter1_29_309_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_29_309_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_29_309_Closed_Text.style.display='none'; Codehighlighter1_29_309_Open_Image.style.display='inline'; Codehighlighter1_29_309_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testSaveComment()</span><span id="Codehighlighter1_29_309_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_29_309_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsComment comment </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> CsComment();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        comment.setCommentDate(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Date());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        comment.setContent(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">comment test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        channelDAO.saveComment(comment);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsComment dbComment </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(CsComment)channelDAO.getEntity(comment.getId());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNotNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">comment has bean saved</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, dbComment);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_343_571_Open_Image" onclick="this.style.display='none'; Codehighlighter1_343_571_Open_Text.style.display='none'; Codehighlighter1_343_571_Closed_Image.style.display='inline'; Codehighlighter1_343_571_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_343_571_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_343_571_Closed_Text.style.display='none'; Codehighlighter1_343_571_Open_Image.style.display='inline'; Codehighlighter1_343_571_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testDeleteComment()</span><span id="Codehighlighter1_343_571_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_343_571_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsComment comment </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> CsComment();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        comment.setId(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Long(</span><span style="COLOR: #000000">13</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        channelDAO.delete(comment);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        CsComment dbComment </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(CsComment)channelDAO.getEntity(comment.getId());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        assertNull(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">comment has bean delete</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, dbComment);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div><br />其实这种save或者delete的方法由于使用时都是基本调用hibernate的方法，所以在我看来测试的意义并不是很大<br /><img src ="http://www.blogjava.net/wuxufeng8080/aggbug/94597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2007-01-18 11:37 <a href="http://www.blogjava.net/wuxufeng8080/articles/94597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iBATIS技巧</title><link>http://www.blogjava.net/wuxufeng8080/articles/88175.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 07:06:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88175.html</guid><description><![CDATA[
		<p>现在项目中使用ibatis作为数据库操作工具，在深感ibatis功能强大的同时，一直也在为如何写出动态SQL而困惑，自己也是在一点点的摸索中，现在发现prepend这个小工具确实不错，下面就是在项目中自己摸索的几个小用法。 </p>
		<p>1：通常用法，也是大多数参考文章上面介绍的方法</p>
		<div class="code_title">xml 代码</div>
		<div class="dp-highlighter">
				<div class="bar">
				</div>
				<ol class="dp-xml">
						<li class="alt">
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">dynamic</span>
										<span> </span>
										<span class="attribute">prepend</span>
										<span>=</span>
										<span class="attribute-value">"where"</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="">
								<span>      </span>
								<span class="tag">&lt;</span>
								<span class="tag-name">isNotEmpty</span>
								<span> </span>
								<span class="attribute">prepend</span>
								<span>=</span>
								<span class="attribute-value">"and"</span>
								<span> </span>
								<span class="attribute">property</span>
								<span>=</span>
								<span class="attribute-value">"csendUserId"</span>
								<span class="tag">&gt;</span>
								<span>        </span>
						</li>
						<li class="alt">
								<span>          </span>
								<span class="attribute">csendUserId</span>
								<span> = #csendUserId#         </span>
						</li>
						<li class="">
								<span>      </span>
								<span class="tag">
										<span class="tag-name">isNotEmpty</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="alt">
								<span>  </span>
								<span class="tag">
										<span class="tag-name">dynamic</span>
										<span class="tag">&gt;</span>
										<span>   </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>
				<font face="Arial">2：通常用法的小小扩充，在里面增加一个and</font>
		</p>
		<div class="code_title">xml 代码</div>
		<div class="dp-highlighter">
				<div class="bar">
				</div>
				<ol class="dp-xml">
						<li class="alt">
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">dynamic</span>
										<span> </span>
										<span class="attribute">prepend</span>
										<span>=</span>
										<span class="attribute-value">"where"</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="">
								<span>    </span>
								<span class="tag">&lt;</span>
								<span class="tag-name">isNotEmpty</span>
								<span> </span>
								<span class="attribute">prepend</span>
								<span>=</span>
								<span class="attribute-value">"and"</span>
								<span> </span>
								<span class="attribute">property</span>
								<span>=</span>
								<span class="attribute-value">"csendUserId"</span>
								<span class="tag">&gt;</span>
								<span>        </span>
						</li>
						<li class="alt">
								<span>        </span>
								<span class="attribute">csendUserId</span>
								<span> = #csendUserId#         </span>
						</li>
						<li class="">
								<span>        and         </span>
						</li>
						<li class="alt">
								<span>        </span>
								<span class="attribute">isenddr</span>
								<span> = </span>
								<span class="attribute-value">0</span>
								<span>        </span>
						</li>
						<li class="">
								<span>    </span>
								<span class="tag">
										<span class="tag-name">isNotEmpty</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="alt">
								<span>
								</span>
								<span class="tag">
										<span class="tag-name">dynamic</span>
										<span class="tag">&gt;</span>
										<span>       </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>
				<font face="Arial">3：在数据库表连接处使用，自己以前从来没有过的想法：）</font>
		</p>
		<div class="code_title">xml 代码</div>
		<div class="dp-highlighter">
				<div class="bar">
				</div>
				<ol class="dp-xml">
						<li class="alt">
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">dynamic</span>
										<span> </span>
										<span class="attribute">prepend</span>
										<span>=</span>
										<span class="attribute-value">"left outer join cms_user U on "</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="">
								<span>    </span>
								<span class="tag">&lt;</span>
								<span class="tag-name">isNotEmpty</span>
								<span> </span>
								<span class="attribute">prepend</span>
								<span>=</span>
								<span class="attribute-value">""</span>
								<span> </span>
								<span class="attribute">property</span>
								<span>=</span>
								<span class="attribute-value">"creceiveUserid"</span>
								<span class="tag">&gt;</span>
								<span>        </span>
						</li>
						<li class="alt">
								<span>        </span>
								<span class="attribute">M.csendUserId</span>
								<span> = U.pk_user         </span>
						</li>
						<li class="">
								<span>    </span>
								<span class="tag">
										<span class="tag-name">isNotEmpty</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="alt">
								<span>
								</span>
								<span class="tag">
										<span class="tag-name">dynamic</span>
										<span class="tag">&gt;</span>
										<span>    </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>
				<font face="Arial">4：检索条件处使用，动态增加检索条件</font>
		</p>
		<div class="code_title">xml 代码</div>
		<div class="dp-highlighter">
				<div class="bar">
				</div>
				<ol class="dp-xml">
						<li class="alt">
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">dynamic</span>
										<span> </span>
										<span class="attribute">prepend</span>
										<span>=</span>
										<span class="attribute-value">""</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="">
								<span>    </span>
								<span class="tag">&lt;</span>
								<span class="tag-name">isNotEmpty</span>
								<span> </span>
								<span class="attribute">prepend</span>
								<span>=</span>
								<span class="attribute-value">""</span>
								<span> </span>
								<span class="attribute">property</span>
								<span>=</span>
								<span class="attribute-value">"creceiveUserid"</span>
								<span class="tag">&gt;</span>
								<span>        </span>
						</li>
						<li class="alt">
								<span>        ,csendUserId         </span>
						</li>
						<li class="">
								<span>        ,U.VTRUENAME as sendUserName         </span>
						</li>
						<li class="alt">
								<span>    </span>
								<span class="tag">
										<span class="tag-name">isNotEmpty</span>
										<span class="tag">&gt;</span>
										<span>        </span>
								</span>
						</li>
						<li class="">
								<span>
								</span>
								<span class="tag">
										<span class="tag-name">dynamic</span>
										<span class="tag">&gt;</span>
										<span>       </span>
								</span>
						</li>
						<li class="alt">
								<span>  </span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>需要注意的是，检索的时候，如果动态检索条件的话，需要增加<font face="Arial">remapResults="true"</font></p>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 15:06 <a href="http://www.blogjava.net/wuxufeng8080/articles/88175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iBATIS如何复用SQL片段(zt)</title><link>http://www.blogjava.net/wuxufeng8080/articles/88167.html</link><dc:creator>风人园</dc:creator><author>风人园</author><pubDate>Sat, 16 Dec 2006 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/wuxufeng8080/articles/88167.html</guid><description><![CDATA[
		<p>
				<font face="Arial">原文链接</font>
		</p>
		<p>
				<font face="Arial">
						<a href="http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+reuse+SQL-fragments">http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+reuse+SQL-fragments</a>
				</font>
		</p>
		<font face="Arial">
				<p>
						<br />When writing SqlMaps, you often encounter duplicate fragments of SQL, for example a FROM-clause or constraint-statement; iBATIS offers a simple yet powerful tag to reuse them. For the sake of simplicity, let's assume we want to get some items and we want to do a count on them.</p>
				<p>Normally, you would write something like this:</p>
				<p>当我们写SqlMaps的时候，经常会碰到重复的SQL片段，例如From语句或者约束条件；iBATIS提供了一个强大的标签来复用这些重复片段，简单举例，我们想检索一些字段，并且想统计它们。</p>
				<p>通常情况下，你会这样写：</p>
				<div class="code_title">xml 代码</div>
				<div class="dp-highlighter">
						<div class="bar">
						</div>
						<ol class="dp-xml">
								<li class="alt">
										<span>
												<span class="tag">&lt;</span>
												<span class="tag-name">select</span>
												<span> </span>
												<span class="attribute">id</span>
												<span>=</span>
												<span class="attribute-value">"selectItemCount"</span>
												<span> </span>
												<span class="attribute">resultClass</span>
												<span>=</span>
												<span class="attribute-value">"int"</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="">
										<span>  SELECT COUNT(*) AS total      </span>
								</li>
								<li class="alt">
										<span>  FROM items      </span>
								</li>
								<li class="">
										<span>  WHERE </span>
										<span class="attribute">parentid</span>
										<span> = </span>
										<span class="attribute-value">6</span>
										<span>     </span>
								</li>
								<li class="alt">
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">&lt;</span>
										<span class="tag-name">select</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"selectItems"</span>
										<span> </span>
										<span class="attribute">resultClass</span>
										<span>=</span>
										<span class="attribute-value">"Item"</span>
										<span class="tag">&gt;</span>
										<span>     </span>
								</li>
								<li class="alt">
										<span>  SELECT id, name      </span>
								</li>
								<li class="">
										<span>  FROM items      </span>
								</li>
								<li class="alt">
										<span>  WHERE </span>
										<span class="attribute">parentid</span>
										<span> = </span>
										<span class="attribute-value">6</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>  </span>
								</li>
						</ol>
				</div>
				<p> <font face="Arial">To eliminate this duplication, we use the tags 【sql】 and 【include】. The 【sql】-tag contains the fragment to reuse, the 【include】-tag to include such a fragment:</font></p>
				<p>
						<font face="Arial">为了消除重复片段，我们使用【sql】和【include】标签。【sql】标签用来包含重复片段，【include】标签用来引入片段：</font>
				</p>
				<p>
						<font face="Arial">
						</font> xml 代码</p>
				<div class="dp-highlighter">
						<div class="bar">
						</div>
						<ol class="dp-xml">
								<li class="alt">
										<span>
												<span class="tag">&lt;</span>
												<span class="tag-name">sql</span>
												<span> </span>
												<span class="attribute">id</span>
												<span>=</span>
												<span class="attribute-value">"selectItem_fragment"</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="">
										<span>  FROM items      </span>
								</li>
								<li class="alt">
										<span>  WHERE </span>
										<span class="attribute">parentid</span>
										<span> = </span>
										<span class="attribute-value">6</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/sql</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>
										</span>
										<span class="tag">&lt;</span>
										<span class="tag-name">select</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"selectItemCount"</span>
										<span> </span>
										<span class="attribute">resultClass</span>
										<span>=</span>
										<span class="attribute-value">"int"</span>
										<span class="tag">&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>  SELECT COUNT(*) AS total      </span>
								</li>
								<li class="alt">
										<span>  </span>
										<span class="tag">&lt;</span>
										<span class="tag-name">include</span>
										<span> </span>
										<span class="attribute">refid</span>
										<span>=</span>
										<span class="attribute-value">"selectItem_fragment"</span>
										<span class="tag">/&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>
										</span>
										<span class="tag">&lt;</span>
										<span class="tag-name">select</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"selectItems"</span>
										<span> </span>
										<span class="attribute">resultClass</span>
										<span>=</span>
										<span class="attribute-value">"Item"</span>
										<span class="tag">&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>  SELECT id, name      </span>
								</li>
								<li class="alt">
										<span>  </span>
										<span class="tag">&lt;</span>
										<span class="tag-name">include</span>
										<span> </span>
										<span class="attribute">refid</span>
										<span>=</span>
										<span class="attribute-value">"selectItem_fragment"</span>
										<span class="tag">/&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>  </span>
								</li>
						</ol>
				</div>
				<p> <font face="Arial">The 【include】-tag is namespace-aware so you can refer to fragments even when they are located in another map (however, due to the way iBATIS loads the SqlMaps, the included fragment should be loaded before the including statement).</font> </p>
				<p>【inclued】标签是一个命名空间可知的，所以你可以引入其他map的片段.(但是，因为iBATIS引入SqlMap的顺序，被引入的片段，要优先于欲引入的sql部分被导入）</p>
				<p>The fragments are included and processed on query-execution so parameters can be used too:</p>
				<p>重复片段在查询执行时被引入和执行，所以参数依然可以使用：</p>
				<p> xml 代码</p>
				<div class="dp-highlighter">
						<div class="bar">
						</div>
						<ol class="dp-xml">
								<li class="alt">
										<span>
												<span class="tag">&lt;</span>
												<span class="tag-name">sql</span>
												<span> </span>
												<span class="attribute">id</span>
												<span>=</span>
												<span class="attribute-value">"selectItem_fragment"</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="">
										<span>  FROM items      </span>
								</li>
								<li class="alt">
										<span>  WHERE </span>
										<span class="attribute">parentid</span>
										<span> = #value#      </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/sql</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>
										</span>
										<span class="tag">&lt;</span>
										<span class="tag-name">select</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"selectItemCount"</span>
										<span> </span>
										<span class="attribute">parameterClass</span>
										<span>=</span>
										<span class="attribute-value">"int"</span>
										<span> </span>
										<span class="attribute">resultClass</span>
										<span>=</span>
										<span class="attribute-value">"int"</span>
										<span class="tag">&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>  SELECT COUNT(*) AS total      </span>
								</li>
								<li class="alt">
										<span>  </span>
										<span class="tag">&lt;</span>
										<span class="tag-name">include</span>
										<span> </span>
										<span class="attribute">refid</span>
										<span>=</span>
										<span class="attribute-value">"selectItem_fragment"</span>
										<span class="tag">/&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>
										</span>
										<span class="tag">&lt;</span>
										<span class="tag-name">select</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"selectItems"</span>
										<span> </span>
										<span class="attribute">parameterClass</span>
										<span>=</span>
										<span class="attribute-value">"int"</span>
										<span> </span>
										<span class="attribute">resultClass</span>
										<span>=</span>
										<span class="attribute-value">"Item"</span>
										<span class="tag">&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>  SELECT id, name      </span>
								</li>
								<li class="alt">
										<span>  </span>
										<span class="tag">&lt;</span>
										<span class="tag-name">include</span>
										<span> </span>
										<span class="attribute">refid</span>
										<span>=</span>
										<span class="attribute-value">"selectItem_fragment"</span>
										<span class="tag">/&gt;</span>
										<span>     </span>
								</li>
								<li class="">
										<span>
										</span>
										<span class="tag">
												<span class="tag-name">&lt;/select</span>
												<span class="tag">&gt;</span>
												<span>     </span>
										</span>
								</li>
								<li class="alt">
										<span>
										</span>
								</li>
						</ol>
				</div>
		</font>
<img src ="http://www.blogjava.net/wuxufeng8080/aggbug/88167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wuxufeng8080/" target="_blank">风人园</a> 2006-12-16 14:38 <a href="http://www.blogjava.net/wuxufeng8080/articles/88167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>