您的位置:首页 > 移动开发

【原创翻译】在AppFuse 2.0 中使用 Hibernate【AppFuse 2.0 文档-10】

2015-05-13 21:25 507 查看
摘要:本文讨论了在AppFuse2.0中使用Hibernate关键字:Appfuse2.0,Hibernate,Maven2,Struct2.0,Spring,UsingHibernate标题:【原创翻译】在AppFuse2.0中使用Hibernate【AppFuse2.0文档-10】作者:AddedbyMattRaible,lasteditedbyMattRaibleonOct24,200700:39翻译者:陈海青(josonchen)(http://www.chq.name)(http://www.hhrz.org)(http://junit.vicp.net)日期:2007.11.15摘要:本文讨论了在AppFuse2.0中使用Hibernate关键字:Appfuse2.0,Hibernate,Maven2,Struct2.0,Spring,[align=left][/align][align=left]英文版网址:http://appfuse.org/display/APF/Using+Hibernate[/align][align=left]关于本节教程[/align][align=left]本教程主要关于以下两件事:[/align][align=left]1.如果仅需要生成CRUD方法,那么不需要书写DAOs[/align][align=left]2.需要定制CRUD方法时,应如何写DAOs.[/align][align=left]如果对Hibernate不太熟悉,也许在开始本课程之前需要读读HibernateReferenceGuide.[/align]目录[align=left]1.注册一个personDaobean定义[/align][align=left]2.建立测试finder方法的DAO测试用例[/align][align=left]3.建立一个DAO接口和实现[/align][align=left]4.运行DAO测试[/align][align=center]
关于源码[/align]本课程的代码位置在Googlecode的appfuse-demos项目里的"tutorial-hibernate"模块里.使用以下命令从Subversion服务器中检出:
svncheckout'target='_blank'>http://appfuse-demos.googlecode.com/svn/trunk/tutorial-hibernate[/code]
注册personDaobean定义AppFuse2.x不需要写DAO来持久化POJO.如果你所需要的仅是对一个对象执行CRUD操作,那就可以使用以下预置的类之一:GenericDaoHibernate:是一个通用的类,需要建立Springbean定义.
UniversalDaoHibernate:一个特殊的类,需要建立指定的对象类型.
UniversalDaoHibernate类已经被注册为一个"dao"bean,所以不必增加附加的配置就可以使用.然而,许多开发者更喜欢通用的DAO(generics-basedDAO),因为它提供了类型安全保证。为注册personDaobean,需要建立文件src/main/webapp/WEB-INF/applicationContext.xml(多模块架构是core/src/main/resources/applicationContext.xml)并添加以下内容:[align=center]
注意,如果使用AppFuse2.0M5+,applicationContext.xml文件可能已经存在了.[/align]
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
'target='_blank'>http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">[/code]
<beanid="personDao"class="org.appfuse.dao.hibernate.GenericDaoHibernate">
<constructor-argvalue="org.appfuse.tutorial.model.Person"/>
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
</beans>
完成后,使用Spring的应用,再添加了以下setter方法后,就可以在一个对象上使用这个bean了:
publicvoidsetPersonDao(GenericDao<Person,Long>personDao){
this.personDao=personDao;
}
如果不仅仅需要CRUD功能,那还要继续向下阅读本教程,否则,可以转而阅读CreatingnewManagers,这篇教程教授如何建立商业逻辑面,与SessionFacades类似,但是不使用EJB技术。这些面(facades)用于提供前端与DAO层的通讯.建立DAO测试类测试finder方法现在需要建立一个DaoTest类来测试DAO是否能工作。"请等一会,"你也许会说,"我还没创建DAO!"当然,你是正确的。然而,我发现测试驱动开发(Test-DrivenDevelopment)更有利于提高软件开发质量.多年来,我一直认为写类前先写测试毫无是处,而且看起来好像是很愚蠢的。但在尝试过以后,我发现这种开发方法实际上是很了不起的。现在,我使用测试驱动的唯一原因就是因为它能迅速提高软件开发效率.首先,在src/test/java/**/daodirectory(多模原型下core/src/test/java/**/dao)目录下建立类PersonDaoTest.java,它要继承org.appfuse.dao.BaseDaoTestCase–是Spring的AbstractTransactionalDataSourceSpringContextTests的一个子类.其父类是用于装载Spring的ApplicationContext(因为Spring需要依据它来把接口(interfaces)绑定到实现上(implementations)),并且(可选的)装入一个与你的*Test类同名的.properties文件.在本例中,如果将一个命名为PersonDaoTest.properties的文件放入目录src/test/resources/org/appfuse/tutorial/dao,那么文件中的属性将可以使用变量"rb"来取得.
packageorg.appfuse.tutorial.dao;
importjava.util.List;
importorg.appfuse.dao.BaseDaoTestCase;
importorg.appfuse.tutorial.model.Person;
importorg.springframework.dao.DataAccessException;
publicclassPersonDaoTestextendsBaseDaoTestCase{
privatePersonDaopersonDao=null;
publicvoidsetPersonDao(PersonDaopersonDao){
this.personDao=personDao;
}
}
上述代码就是一个基本的与Spring整合的测试,初始化,并配置了PersonDao的实现.Spring将通过名字来自动回调setPersonDao()方法,并建立与"personDao"bean的关联.现在可以测试DAO中的finder方法了。首先建立一个以"test"(全部小写)开头的测试类.,访问权限是public,返回类型为void,没有参数,它将被Junit调用执行,然后将以下方法加入PersonDaoTest.java文件:
publicvoidtestFindPersonByLastName()throwsException{
List<Person>people=personDao.findByLastName("Raible");
assertTrue(people.size()>0);
}
你会注意到,这个方法要测试通过必须要依赖一些预置的数据,而DbUnitMavenPlugin可以用来在测试运行前将数据插入数据库中,你只需将需加入的表或记录的信息放到文件src/test/resources/sample-data.xml中(多模原型是在core/src/test/resources/sample-data.xml),以下为示例:
<tablename='person'>
<column>id</column>
<column>first_name</column>
<column>last_name</column>
<row>
<value>1</value>
<value>Matt</value>
<value>Raible</value>
</row>
</table>
[align=center]
如果重新格式sample-data.xml中的XML,要确保在标签(tag)值内没有换行符(linebreaks).但令我吃惊的是当<password>xxxxxxx</password>被分为三行的情景,由于password标签不再对额外的tabs和换行符进行解密,现在想用任意用户名登录将不再可能。而允许在数据库连接串里使用任意字符是DBUnit的特性.[/align]
由于将要写的PersonDao包含了CRUD功能,所以也要写个校验CRUD的测试.
importorg.springframework.dao.DataAccessException;
publicvoidtestAddAndRemovePerson()throwsException{
Personperson=newPerson();
person.setFirstName("Country");
person.setLastName("Bry");
person=personDao.save(person);
flush();
person=personDao.get(person.getId());
assertEquals("Country",person.getFirstName());
assertNotNull(person.getId());
log.debug("removingperson...");
personDao.remove(person.getId());
flush();
try{
personDao.get(person.getId());
fail("Personfoundindatabase");
}catch(DataAccessExceptiondae){
log.debug("Expectedexception:"+dae.getMessage());
assertNotNull(dae);
}
}
上例中,在保存对象前,要先调用person.set*(value)方法设置对象,然后再保存起来。本例情况较简单,如果对象的属性超过了10个,那就麻烦了。这就是为什么在BaseDaoTestCase要有一个资源集合(ResourceBundle)的原因.首先在PersonDaoTest.java所在目录里简单地建立一个PersonDaoTest.properties文件,并定义属性值对如下:
firstName=Matt
lastName=Raible
[align=center]
也许觉得可以用硬编码来在程序里设置测试值,但是在处理大的对象时,.properties文件是一个很好的选择.[/align]
然后,不必调用person.set*来设置对象属性,只需使用BaseDaoTestCase.populate(java.lang.Object)方法即可完成:
Personperson=newPerson();
person=(Person)populate(person);
此时,PersonDaoTest类还不能编译,因为还没有PersonDao类,现在需要建立它了.建立DAO接口及其实现在src/main/java/**/dao(多模原型是core/src/main/java/**/dao)目录里建立接口文件PersonDao.java,并为所有的实现类指定finder方法.
packageorg.appfuse.tutorial.dao;
importorg.appfuse.dao.GenericDao;
importorg.appfuse.tutorial.model.Person;
importjava.util.List;
publicinterfacePersonDaoextendsGenericDao<Person,Long>{
publicList<Person>findByLastName(StringlastName);
}
注意,上面这个类的方法声明(methodsignature)中并没有异常声明,这主要是归功于Spring,它使用RuntimeExceptions包装了异常(Exception).现在,你可以使用IDE或命令mvntest-compile来编译代码了.然而,如果你试图运行mvntest-Dtest=PersonDaoTest,就会报错:
Runningorg.appfuse.tutorial.dao.PersonDaoTest
INFO-AbstractSingleSpringContextTests.loadContextLocations(179)|Loadingcontextfor:classpath*:/applicationContext-*.xml
Testsrun:2,Failures:0,Errors:2,Skipped:0,Timeelapsed:0.449sec<<<FAILURE!
很不幸,这些信息并没有多少关于是导致报错的原因的,要找到问题所在,需要打开文件target/surefire-reports/org.appfuse.tutorial.dao.PersonDaoTest.txt(在多模原型下是core/target/surefire-reports/org.appfuse.tutorial.dao.PersonDaoTest.txt),在这里会告诉你有真正的问题所在:
---------------------------------------------------------------------
Testset:org.appfuse.tutorial.dao.PersonDaoTest
---------------------------------------------------------------------
Testsrun:2,Failures:0,Errors:2,Skipped:0,Timeelapsed:0.444sec<<<FAILURE!
testFindPersonByLastName(org.appfuse.tutorial.dao.PersonDaoTest)Timeelapsed:0.401sec<<<ERROR!
org.springframework.beans.factory.UnsatisfiedDependencyException:Errorcreatingbean
withname'org.appfuse.tutorial.dao.PersonDaoTest':Unsatisfieddependencyexpressed
throughbeanproperty'personDao':Setthispropertyvalueordisabledependency
checkingforthisbean.
[align=center]
在控制台(控制窗口)中显示错误
mvntest命令里添加参数-Dsurefire.useFile=false就可以在控制台(console)中现实测试错误信息。[/align]
这个错误信息来自Spring–指出需要在Spring的context文件里指定一个命名为"personDao"的bean.在做这件事之前,首先需要建立PersonDao的实现类.我们建立一个PersonDaoHibernate类来实现PersonDao里的finder方法.首先,在src/main/java/**/dao/hibernate(多模原型core/src/main/java/**/dao/hibernate)目录下建立一个类文件,并命名为PersonDaoHibernate.java.需要继承GenericDaoHibernate并且实现PersonDao。一个简短的例子如下:
packageorg.appfuse.tutorial.dao.hibernate;
importjava.util.List;
importorg.appfuse.dao.hibernate.GenericDaoHibernate;
importorg.appfuse.tutorial.model.Person;
importorg.appfuse.tutorial.dao.PersonDao;
publicclassPersonDaoHibernateextendsGenericDaoHibernate<Person,Long>implementsPersonDao{
publicPersonDaoHibernate(){
super(Person.class);
}
publicList<Person>findByLastName(StringlastName){
returngetHibernateTemplate().find("fromPersonwherelastName=?",lastName);
}
}
现在如果再运行mvntest-Dtest=PersonDaoTest,还会看到同样的错误,因为还要配置Spring告诉它PersonDaoHibernate是PersonDao.的实现类。在src/main/webapp/WEB-INF(orcore/src/main/resourcesforamodulararchetype)目录下建立文件applicationContext.xml,并添加以下内容分:
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
'target='_blank'>http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">[/code]
<beanid="personDao"class="org.appfuse.tutorial.dao.hibernate.PersonDaoHibernate">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
</beans>
运行DAO测试保存编辑的文件,运行命令mvntest-Dtest=PersonDaoTest,过一会后,是的,朋友,就是这条信息:BUILDSUCCESSFUL
Totaltime:9seconds[align=center]
在视图过滤器(ViewFilter)中打开会话(Session
如果希望在应用中使用Hibernate的延迟载入(lazy-loading)特性,那么,需要在文件web.xml中去掉lazyLoadingFilter(及其mapping)的注释.[/align]
[align=center][/align]接下来:PartII:建立管理类(CreatingnewManagers)-关于如何建立商业逻辑层(BusinessFacades),与会话层(SessionFacades)类似,但是不使用EJB.这些层用于提供前台(front-end)与DAO层的通讯。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: