??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人综合一区二区三区,亚洲高清视频一区,高清色视频在线观看http://www.aygfsteel.com/wuxufeng8080/category/18455.htmlzh-cnWed, 07 Mar 2007 16:27:02 GMTWed, 07 Mar 2007 16:27:02 GMT60Don’t repeat the DAO!http://www.aygfsteel.com/wuxufeng8080/articles/101870.html风h?/dc:creator>风h?/author>Mon, 05 Mar 2007 03:51:00 GMThttp://www.aygfsteel.com/wuxufeng8080/articles/101870.html译者:Nicholas @ Nirvana Studio
原文地址Qhttp://www-128.ibm.com/developerworks/java/library/j-genericdao.html

使用Hibernate和Spring AOP购徏一个范型类型安全的DAO
2006q五?2?br />

在采用了Java 5的范型之后,要实C个基于范型类型安全的数据讉K对象QDAOQ就变得切实可行了。在q篇文章里,pȝ架构师Per Mellqvist展示了一个基于Hibernate的范型DAO实现。然后将介绍如何使用Spring AOP的introductionZ个类增加一个类型安全的接口以便于执行查询?/blockquote>

对于大多数开发者来_在系l中为每一个DAO~写几乎一L代码已经成ؓ了一U习惯。同时大家也都认可这U重复就是“代码的味道”,我们中的大多数已l习惯如此。当然也有另外的办法。你可以使用很多ORM工具来避免代码的重复~写。D个例子,用HibernateQ你可以单的使用session操作直接控制你的持久化领域对象。这U方式的负面影响是丢失了类型安全?

Z么你的数据访问代码需要一个类型安全的接口Q我认ؓ它减了~程错误Q提高了生率,其是在使用C高IDE的时候。首先,一个类型安全的接口清晰的制定了哪些领域对象h持久化功能。其ơ,它消除了cd转换带来的潜在问题。最后,它^衡了IDE的自动完成功能。用自动完成功能是最快的方式来记住对于适当的领域类哪些查询是可用的?

在这文章里Q我展C给大家如何避免一ơ次地重复编写DAO代码Q但同时q收益于cd安全的接口。事实上Q所有内需要编写的是ؓ新的DAO~写一个Hibernate映射文gQ一个POJO的Java接口Qƈ?0行Spring配置文g?

DAO实现

DAO模式对于MJava开发h员来说都是耳熟能详的。这个模式的实现相当多,所以让我们仔细推敲一下我q篇文章里面对于DAO实现的一些假设:

  • 所有系l中的数据库讉K都是通过DAO来完成封?
  • 每一个DAO实例对一个主要的领域对象或者实体负责。如果一个领域对象具有独立的生命周期Q那么它需要具有自qDAO?
  • DAOhCRUD操作
  • DAO可以允许Zcriteria方式的查询而不仅仅是通过主键查询。我这些成为finderҎ或者finders。这个finder的返回值通常是DAO所负责的领域对象的集合?

范型DAO接口

范型DAO的基是CRUD操作。下面的接口定义了范型DAO的方法:

						public
						interface GenericDao <T, PK extends Serializable> {
 
    /** Persist the newInstance object into database */
    PK create(T newInstance);
 
    /** Retrieve an object that was previously persisted to the database using
     *   the indicated id as primary key
     */
    T read(PK id);
 
    /** Save changes made to a persistent object.  */void update(T transientObject);
 
    /** Remove an object from persistent storage in the database */void delete(T persistentObject);
}

实现q个接口

使用Hibernate实现上面的接口是非常单的。也是调用一下Hibernate的方法和增加一些类型{换。Spring负责session和transaction理?

						public
						class GenericDaoHibernateImpl <T, PK extends Serializable>
    implements GenericDao<T, PK>, FinderExecutor {private Class<T> type;
 
    public GenericDaoHibernateImpl(Class<T> type){this.type = type;
    }
 
    public PK create(T o){return(PK) getSession().save(o);
    }
 
    public T read(PK id){return(T) getSession().get(type, id);
    }
 
    publicvoid update(T o){
        getSession().update(o);
    }
 
    publicvoid delete(T o){
        getSession().delete(o);
    }
 
    // Not showing implementations of getSession() and setSessionFactory()}

Spring 配置

最后,Spring配置Q我创徏了一个GenericDaoHibernateImpl的实例。GenericDaoHibernateImpl的构造器必须被告知领域对象的cdQ这样DAO实例才能Z负责。这个同样需要Hibernateq行时知道这个对象的cd。下面的代码中,我将领域cPerson传递给构造器q且Hibernate的session工厂作ؓ一个参数用来实例化DAOQ?

						
								<bean
								id="personDao"class="genericdao.impl.GenericDaoHibernateImpl">
						
								<constructor-arg>
						
						
								<value>
						genericdaotest.domain.Person</value></constructor-arg><propertyname="sessionFactory"><refbean="sessionFactory"/></property></bean>

可用的范型DAO

我还没有全部完成Q但我现在已l有了一个可供作的代码。下面的代码展示了范型DAO如何使用Q?

						public
						void someMethodCreatingAPerson(){
    ...
    GenericDao dao = (GenericDao)
     beanFactory.getBean("personDao"); // This should normally be injected
 
    Person p = new Person("Per", 90);
    dao.create(p);
}

q时候,我有一个范型DAO有能力进行类型安全的CRUD操作。同时也有理q写GenericDaoHibernateImpl的子cL为每个领域对象增加查询功能。但是这文章的L在于展示如何完成q项功能而不是ؓ每个查询~写明确的代码,然而,我将会用多个工h介绍DAO的查询,q就是Spring AOP和Hibernate命名查询?

Spring AOP介绍

你可以用Spring AOP提供的introduction功能一个现存的对象包装C个代理里面来增加新的功能Q定义它需要实现的新接口,q且之前所有不支持的方法委zֈ一个处理机。在我的DAO实现里面Q我用introduction一定数量的finderҎ增加到现存的范型DAOc里面。因为finderҎ针对特定的领域对象,所以它们被应用到表明接口的范型DAO中?

						
								<bean
								id="finderIntroductionAdvisor"class="genericdao.impl.FinderIntroductionAdvisor"/>
 
<beanid="abstractDaoTarget"class="genericdao.impl.GenericDaoHibernateImpl"abstract="true"><propertyname="sessionFactory"><refbean="sessionFactory"/></property></bean>
 
<beanid="abstractDao"class="org.springframework.aop.framework.ProxyFactoryBean"abstract="true"><propertyname="interceptorNames"><list><value>finderIntroductionAdvisor</value></list></property></bean>

在上面的配置中,我定义了三个Spring beanQ第一个beanQFinderIntroductionAdvisorQ处理那些introduce到DAO中但是不属于GenericDaoHibernateImplcȝҎ。一会我再介lAdvisor bean的详l情c?

W二个bean定义为“abstract”。在Spring中,q个bean可以被其他bean重用但是它自׃会被实例化。不同于抽象属性,bean的定义简单的指出了我需要一个GenericDaoHibernateImpl的实例同旉要一个SessionFactory的引用。注意GenericDaoHibernateImplcd定义了一个构造器接受领域cM为参数。因个bean是抽象的Q我可以无限ơ的重用q且讑֮合适的领域cR?

最后,W三个,也是最有意思的是beanGenericDaoHibernateImpl的实例包装进了一个代理,l予了它执行finderҎ的能力。这个bean定义同样是抽象的q且没有指定M接口。这个接口不同于M具体的实例?

扩展通用DAO

每个DAO的接口,都是ZGenericDAO接口的。我需要将为特定的领域c适配接口q且其扩展包含我的finderҎ?

						public
						interface PersonDao extends GenericDao<Person, Long> {
    List<Person> findByName(String name);
}

上面的代码清晰的展示了通过用户名查找Person对象列表。所需的Java实现cM需要包含Q何的更新操作Q因些已l包含在了通用DAO里?

配置PersonDao

因ؓSpring配置依赖之前的那些抽象beanQ所以它变得很紧凑。我需要指定DAO负责的领域类Qƈ且我需要告诉Spring我这个DAO需要实现的接口?

						
								<bean
								id="personDao"parent="abstractDao">
						
								<property
								name="proxyInterfaces">
						
								<value>
						genericdaotest.dao.PersonDao</value></property><propertyname="target"><beanparent="abstractDaoTarget"><constructor-arg><value>genericdaotest.domain.Person</value></constructor-arg></bean></property></bean>

你可以这样用:

						public
						void someMethodCreatingAPerson(){
    ...
    PersonDao dao = (PersonDao)
     beanFactory.getBean("personDao"); // This should normally be injected
 
    Person p = new Person("Per", 90);
    dao.create(p);
 
    List<Person> result = dao.findByName("Per"); // Runtime exception}

上面的代码是使用cd安全接口PersonDao的一U正途径Q但是DAO的实现ƈ没有完成。当调用findByName()的时候导致了一个运行时异常。这个问题是我还没有findByName()。剩下的工作是指定查询语句。要完成q个Q我使用Hibernate命名查询?

Hibernate命名查询

使用HibernateQ你可以定义MHQL查询在映文仉Qƈ且给它一个名字。你可以在之后的代码里面方便的通过名字引用q个查询。这么做的一个优点就是能够在部v的时候调节查询而不需要改变代码。正如你一会将看到的,另一个好处就是实C个“完整”的DAO而不需要编写Q何Java实现代码?

						
								<hibernate-mapping
								package="genericdaotest.domain">
						
								<class
								name="Person">
						
								<id
								name="id">
						
								<generator
								class="native"/>
						
								</id>
						
						
								<property
								name="name"/>
						
								<property
								name="weight"/>
						
								</class>
						
 
     <queryname="Person.findByName"><![CDATA[select p from Person p where p.name = ? ]]></query></hibernate-mapping>

上面的代码定义了领域cPerson的Hibernate映射文gQ有两个属性:name和weight。Person是一个具有上面属性的单的POJO。这个文件同时包含了一个查询,通过提供的name属性从数据库查找Person实例。Hibernate为命名查询提供了不真实的命名I间功能。ؓ了便于讨论,我将所有的查询名字的前~变成领域cȝ的名U。在现实场景中,使用完整的类名,包含包名Q是一个更好的L?

总览

你已l看CZQ何领域对象创建ƈ配置DAO的所需步骤了。这三个单的步骤是Q?

  1. 定义一个接口承GenericDaoq且包含M所需的finderҎ
  2. 在映文件中为每个领域类的finderҎ增加一个命名查询?
  3. 为DAO增加10行Spring配置

可重用的DAOc?/h2>

Spring advisor和interceptor的功能比较琐,事实上他们的工作都引用回了GenericDaoHibernateImplcR所有带有“find”开头的Ҏ都被传递给DAO的单一ҎexecuteFinder()?

						public
						class FinderIntroductionAdvisor extends DefaultIntroductionAdvisor {public FinderIntroductionAdvisor(){super(new FinderIntroductionInterceptor());
    }}
 
publicclass FinderIntroductionInterceptor implements IntroductionInterceptor {
 
    publicObject invoke(MethodInvocation methodInvocation)throwsThrowable{
 
        FinderExecutor genericDao = (FinderExecutor) methodInvocation.getThis();
 
        String methodName = methodInvocation.getMethod().getName();
        if(methodName.startsWith("find")){Object[] arguments = methodInvocation.getArguments();
            return genericDao.executeFinder(methodInvocation.getMethod(), arguments);
        }else{return methodInvocation.proceed();
        }}
 
    publicboolean implementsInterface(Class intf){return intf.isInterface() && FinderExecutor.class.isAssignableFrom(intf);
    }}

executeFinder() Ҏ

上面的代码唯一~的是executeFinder的实现。这个代码观察被调用的类的名字和ҎQƈ且将他们与Hibernate的查询名相匹配。你可以使用一个FinderNamingStrategy来激zd他方式的命名查询。默认的实现查找一个名为“ClassName.methodName”的查询QClassName是除包名之外的类名?

						public List<T> executeFinder(Method method, finalObject[] queryArgs){finalString queryName = queryNameFromMethod(method);
     finalQuery namedQuery = getSession().getNamedQuery(queryName);
     String[] namedParameters = namedQuery.getNamedParameters();
     for(int i = 0; i < queryArgs.length; i++){Object arg = queryArgs[i];
             Type argType =  namedQuery.setParameter(i, arg);
      }return(List<T>) namedQuery.list();
}
 
publicString queryNameFromMethod(Method finderMethod){return type.getSimpleName() + "." + finderMethod.getName();
}

ȝ

在Java 5之前QJava语言q不支持代码同时hcd安全和范性的Ҏ;你不得不二者选一。在q篇文章里,你可以看C用Java 5范型支持q且l合Spring和HibernateQ和AOPQ一h提高生力。一个范型类型安全的DAOc非常容易编写,所有你需要做的就是一个接口,一些命名查询,q且10行Spring配置Qƈ且可以极大的减少错误Q同时节省时间?



]]>Spring DAO 试http://www.aygfsteel.com/wuxufeng8080/articles/94597.html风h?/dc:creator>风h?/author>Thu, 18 Jan 2007 03:37:00 GMThttp://www.aygfsteel.com/wuxufeng8080/articles/94597.html首先我们来确认一下dao需要什么样的环境,我的dao是用Spring+hibernate来构建的Q而对应的数据源是oracle9。所以要q行dao的测试我需要从Spring的连接oracle的context中获取dao的实例出来,q里我用的是spring-mock
spring-mock使用比较单的Q只需要设|spring的配|文件\径就可以获得上下文了
q里需要注意的是这个spring上下文是ClassPathApplicationContext,而我们在web环境中经帔R到的是WebApplicationContext
/**
 * $Id:$
 *
 * Copyright 2005 easou, Inc. All Rights Reserved.
 
*/

package test.spring.common;

import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

import test.PathConfig;

public class BaseSpringTestCase extends
        AbstractTransactionalDataSourceSpringContextTests 
{    

    @Override
    
protected String[] getConfigLocations() {

        String[] config 
= PathConfig.springxml;

        
return config;

    }
        
    
public void testConfig() {        
        assertNotNull(
"spring-mock context has bean init()",this.applicationContext);
    }


}
q里testConfig是用来检查你spring配置的加载是否正的

下面l出一个DAO的简单查询方?
public List getHomepageAreasByChannelId(long channelId) {

        
return this.executeHQL(" from CsHomepageArea  h where h.csChannel.id='"
                
+ channelId + "' order by h.theOrder");
    }


上面的方法指C根据一个id取列表出来,而我们要试的目标有Q其实也是我们q个Ҏ要实现的目标Q:
1、给出正的id是否能否q回正确的结?br />2、返回的l果集能够根据hibernate配置文g而得到我们期望的l果集(比如说对子集的lazydQ?br />3、返回的l果集是否按照你所期望的排?br />4、给出错误的id是否在获取数据时会出?br />Ҏ上面的测试目标我们就很容易的得到下面的测试方法了

public void testGetHomepageAreasByChannelId() {
        List list 
= channelDAO.getHomepageAreasByChannelId(1);
        assertNotNull(
"homepage list is not null", list);
        CsHomepageArea homepage 
= (CsHomepageArea) list.get(0);
        assertNotNull(
"homepage'name is not null", homepage.getName());
        assertNotNull(
"homepage'channel has been lazy", homepage.getCsChannel()
                .getName());
        assertNotNull(
"homepage'column has been lazy", homepage.getCsColumn()
                .getName());
        assertNotNull(
"homepage'subject has been lazy", homepage
                .getCsSubjects().iterator().next().getName());
        CsSubject subject 
= (CsSubject) homepage.getCsSubjects().iterator()
                .next();
        assertNotNull(
"homepage'subject'keyword has been lazy", subject
                .getCsSubjectKeywords().iterator().next().getName());

    }

对于DAO层的查询ҎQ我们测试的是判断q回的数据是否是我们需要的

下面q个Ҏ是DAO的增Ҏ法,和删除方?br />

public void saveComment(CsComment comment) {
        getHibernateTemplate().saveOrUpdate(comment);        
    }

    
public void deleteComment(CsComment comment) {        
        getHibernateTemplate().delete(comment);        
    }

 

对于q种无返回值得Ҏ我们主要试的是Q?br />1、对于正的数据是否能够正确的存入数据库或者从数据库删?br />2、对于错误的数据操作能够有错误信息(如主键重复)

public void testSaveComment(){
        CsComment comment 
= new CsComment();
        comment.setCommentDate(
new Date());
        comment.setContent(
"comment test");
        channelDAO.saveComment(comment);
        CsComment dbComment 
=(CsComment)channelDAO.getEntity(comment.getId());
        assertNotNull(
"comment has bean saved", dbComment);
    }

    
public void testDeleteComment(){
        CsComment comment 
= new CsComment();
        comment.setId(
new Long(13));
        channelDAO.delete(comment);
        CsComment dbComment 
=(CsComment)channelDAO.getEntity(comment.getId());
        assertNull(
"comment has bean delete", dbComment);
    }

其实q种save或者delete的方法由于用时都是基本调用hibernate的方法,所以在我看来测试的意义q不是很?br />

]]>
iBATIS技?/title><link>http://www.aygfsteel.com/wuxufeng8080/articles/88175.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Sat, 16 Dec 2006 07:06:00 GMT</pubDate><guid>http://www.aygfsteel.com/wuxufeng8080/articles/88175.html</guid><description><![CDATA[ <p>现在目中用ibatis作ؓ数据库操作工P在深感ibatis功能强大的同Ӟ一直也在ؓ如何写出动态SQL而困惑,自己也是在一点点的摸索中Q现在发现prependq个工L实不错,下面是在项目中自己摸烦的几个小用法?</p> <p>1Q通常用法Q也是大多数参考文章上面介l的Ҏ</p> <div id="wmqeeuq" class="code_title">xml 代码</div> <div id="wmqeeuq" class="dp-highlighter"> <div id="wmqeeuq" class="bar"> </div> <ol class="dp-xml"> <li id="wmqeeuq" class="alt"> <span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">dynamic</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"where"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class=""> <span>      </span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"and"</span> <span> </span> <span id="wmqeeuq" class="attribute">property</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"csendUserId"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </li> <li id="wmqeeuq" class="alt"> <span>          </span> <span id="wmqeeuq" class="attribute">csendUserId</span> <span> = #csendUserId#         </span> </li> <li id="wmqeeuq" class=""> <span>      </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class="alt"> <span>  </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">dynamic</span> <span id="wmqeeuq" class="tag">></span> <span>   </span> </span> </li> </ol> </div> <p> </p> <p> <font face="Arial">2Q通常用法的小扩充,在里面增加一个and</font> </p> <div id="wmqeeuq" class="code_title">xml 代码</div> <div id="wmqeeuq" class="dp-highlighter"> <div id="wmqeeuq" class="bar"> </div> <ol class="dp-xml"> <li id="wmqeeuq" class="alt"> <span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">dynamic</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"where"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class=""> <span>    </span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"and"</span> <span> </span> <span id="wmqeeuq" class="attribute">property</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"csendUserId"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </li> <li id="wmqeeuq" class="alt"> <span>        </span> <span id="wmqeeuq" class="attribute">csendUserId</span> <span> = #csendUserId#         </span> </li> <li id="wmqeeuq" class=""> <span>        and         </span> </li> <li id="wmqeeuq" class="alt"> <span>        </span> <span id="wmqeeuq" class="attribute">isenddr</span> <span> = </span> <span id="wmqeeuq" class="attribute-value">0</span> <span>        </span> </li> <li id="wmqeeuq" class=""> <span>    </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class="alt"> <span> </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">dynamic</span> <span id="wmqeeuq" class="tag">></span> <span>       </span> </span> </li> </ol> </div> <p> </p> <p> <font face="Arial">3Q在数据库表q接处用,自己以前从来没有q的xQ)</font> </p> <div id="wmqeeuq" class="code_title">xml 代码</div> <div id="wmqeeuq" class="dp-highlighter"> <div id="wmqeeuq" class="bar"> </div> <ol class="dp-xml"> <li id="wmqeeuq" class="alt"> <span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">dynamic</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"left outer join cms_user U on "</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class=""> <span>    </span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">""</span> <span> </span> <span id="wmqeeuq" class="attribute">property</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"creceiveUserid"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </li> <li id="wmqeeuq" class="alt"> <span>        </span> <span id="wmqeeuq" class="attribute">M.csendUserId</span> <span> = U.pk_user         </span> </li> <li id="wmqeeuq" class=""> <span>    </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class="alt"> <span> </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">dynamic</span> <span id="wmqeeuq" class="tag">></span> <span>    </span> </span> </li> </ol> </div> <p> </p> <p> <font face="Arial">4Q检索条件处使用Q动态增加检索条?/font> </p> <div id="wmqeeuq" class="code_title">xml 代码</div> <div id="wmqeeuq" class="dp-highlighter"> <div id="wmqeeuq" class="bar"> </div> <ol class="dp-xml"> <li id="wmqeeuq" class="alt"> <span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">dynamic</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">""</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class=""> <span>    </span> <span id="wmqeeuq" class="tag"><</span> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span> </span> <span id="wmqeeuq" class="attribute">prepend</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">""</span> <span> </span> <span id="wmqeeuq" class="attribute">property</span> <span>=</span> <span id="wmqeeuq" class="attribute-value">"creceiveUserid"</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </li> <li id="wmqeeuq" class="alt"> <span>        ,csendUserId         </span> </li> <li id="wmqeeuq" class=""> <span>        ,U.VTRUENAME as sendUserName         </span> </li> <li id="wmqeeuq" class="alt"> <span>    </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">isNotEmpty</span> <span id="wmqeeuq" class="tag">></span> <span>        </span> </span> </li> <li id="wmqeeuq" class=""> <span> </span> <span id="wmqeeuq" class="tag"> <span id="wmqeeuq" class="tag-name">dynamic</span> <span id="wmqeeuq" class="tag">></span> <span>       </span> </span> </li> <li id="wmqeeuq" class="alt"> <span>  </span> </li> </ol> </div> <p> </p> <p>需要注意的是,索的时候,如果动态检索条件的话,需要增?font face="Arial">remapResults="true"</font></p> <img src ="http://www.aygfsteel.com/wuxufeng8080/aggbug/88175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wuxufeng8080/" target="_blank">风h?/a> 2006-12-16 15:06 <a href="http://www.aygfsteel.com/wuxufeng8080/articles/88175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iBATIS如何复用SQL片段(zt)http://www.aygfsteel.com/wuxufeng8080/articles/88167.html风h?/dc:creator>风h?/author>Sat, 16 Dec 2006 06:38:00 GMThttp://www.aygfsteel.com/wuxufeng8080/articles/88167.html 原文链接

http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+reuse+SQL-fragments


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.

Normally, you would write something like this:

当我们写SqlMaps的时候,l常会碰到重复的SQL片段Q例如From语句或者约束条ӞiBATIS提供了一个强大的标签来复用这些重复片D,单D例,我们x索一些字D,q且想统计它们?/p>

通常情况下,你会q样写:

xml 代码
  1. < select   id = "selectItemCount"   resultClass = "int" >      
  2.   SELECT COUNT(*) AS total      
  3.   FROM items      
  4.   WHERE  parentid  =  6      
  5. </select >      
  6. < select   id = "selectItems"   resultClass = "Item" >      
  7.   SELECT id, name      
  8.   FROM items      
  9.   WHERE  parentid  =  6      
  10. </select >      
  11.   

 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:

Z消除重复片段Q我们用【sql】和【include】标{。【sql】标{来包含重复片D,【include】标{来引入片D:

 xml 代码

  1. < sql   id = "selectItem_fragment" >      
  2.   FROM items      
  3.   WHERE  parentid  =  6      
  4. </sql >      
  5. < select   id = "selectItemCount"   resultClass = "int" >      
  6.   SELECT COUNT(*) AS total      
  7.    < include   refid = "selectItem_fragment" />      
  8. </select >      
  9. < select   id = "selectItems"   resultClass = "Item" >      
  10.   SELECT id, name      
  11.    < include   refid = "selectItem_fragment" />      
  12. </select >      
  13.   

 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). 

【inclued】标{是一个命名空间可知的Q所以你可以引入其他map的片D?(但是Q因为iBATIS引入SqlMap的顺序,被引入的片段Q要优先于欲引入的sql部分被导入)

The fragments are included and processed on query-execution so parameters can be used too:

重复片段在查询执行时被引入和执行Q所以参C然可以用:

 xml 代码

  1. < sql   id = "selectItem_fragment" >      
  2.   FROM items      
  3.   WHERE  parentid  = #value#      
  4. </sql >      
  5. < select   id = "selectItemCount"   parameterClass = "int"   resultClass = "int" >      
  6.   SELECT COUNT(*) AS total      
  7.    < include   refid = "selectItem_fragment" />      
  8. </select >      
  9. < select   id = "selectItems"   parameterClass = "int"   resultClass = "Item" >      
  10.   SELECT id, name      
  11.    < include   refid = "selectItem_fragment" />      
  12. </select >      


]]>
վ֩ģ壺 ȫ| ½| Ѿ| | ½| üɽ| | | | ˫Ѽɽ| | Ҧ| | | ó| | | | | | | пѷ| ̩| | ߺ| Ƶ| | | ֹ| | | ͸| | Դ| | ˼é| ĺ| | | | ɽ|