【原创翻译】在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]
注册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]
关于源码[/align]本课程的代码位置在Googlecode的svncheckout |
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]由于将要写的PersonDao包含了CRUD功能,所以也要写个校验CRUD的测试.
如果重新格式sample-data.xml中的XML,要确保在标签(tag)值内没有换行符(linebreaks).但令我吃惊的是当<password>xxxxxxx</password>被分为三行的情景,由于password标签不再对额外的tabs和换行符进行解密,现在想用任意用户名登录将不再可能。而允许在数据库连接串里使用任意字符是DBUnit的特性.[/align] 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=MattlastName=Raible[align=center]然后,不必调用person.set*来设置对象属性,只需使用BaseDaoTestCase.populate(java.lang.Object)方法即可完成:
也许觉得可以用硬编码来在程序里设置测试值,但是在处理大的对象时,.properties文件是一个很好的选择.[/align] 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.PersonDaoTestINFO-AbstractSingleSpringContextTests.loadContextLocations(179)|Loadingcontextfor:classpath*:/applicationContext-*.xmlTestsrun: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:Errorcreatingbeanwithname'org.appfuse.tutorial.dao.PersonDaoTest':Unsatisfieddependencyexpressedthroughbeanproperty'personDao':Setthispropertyvalueordisabledependencycheckingforthisbean.[align=center]这个错误信息来自Spring–指出需要在Spring的context文件里指定一个命名为"personDao"的bean.在做这件事之前,首先需要建立PersonDao的实现类.我们建立一个PersonDaoHibernate类来实现PersonDao里的finder方法.首先,在src/main/java/**/dao/hibernate(多模原型core/src/main/java/**/dao/hibernate)目录下建立一个类文件,并命名为PersonDaoHibernate.java.需要继承GenericDaoHibernate并且实现PersonDao。一个简短的例子如下:
在控制台(控制窗口)中显示错误
在mvntest命令里添加参数-Dsurefire.useFile=false就可以在控制台(console)中现实测试错误信息。[/align]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][align=center][/align]接下来:PartII:建立管理类(
在视图过滤器(ViewFilter)中打开会话(Session)
如果希望在应用中使用Hibernate的延迟载入(lazy-loading)特性,那么,需要在文件web.xml中去掉lazyLoadingFilter(及其mapping)的注释.[/align]CreatingnewManagers)-关于如何建立商业逻辑层(BusinessFacades),与会话层( SessionFacades)类似,但是不使用EJB.这些层用于提供前台(front-end)与DAO层的通讯。
相关文章推荐
- 【原创翻译】使用Hibernate持久化java 5 的枚举类型【AppFuse 2.0 文档-11】
- 【原创翻译】AppFuse 2.0 的Readme 文档【船长AppFuse文档-2】
- [原创翻译]Maven2 (for AppFuse)新手入门[AppFuse 2.0文档-7]
- 【原创翻译】AppFuse2.0 开发环境【AppFuse2 文档-5】
- 【船长的AppFuse原创文档-1】【翻译】AppFuse 2.0 发布了
- 【原创翻译】AppFuse 2.0之持久化【AppFuse 2.0 文档-9】
- 【原创翻译】AppFuse 2.0 开发环境【AppFuse2 文档-5】
- 【原创翻译】AppFuse 2.0 快速起步【AppFuse文档-4】
- 【原创翻译】如何在本地主机上使用tbdev建立一台bt Tracker服务器【网站建设文档】
- 在AppFuse 2.0中使用Hibernate来写DAO
- Dialogue System for Unity文档中英对照版(简雨原创翻译)完结篇(内置脚本使用,脚本API)
- 【原创翻译】安装设置Candy【AppFuse文档-8】
- 【原创翻译】SMTP服务器的安装【AppFuse文档-6】
- 【船长的AppFuse原创文档-3】【翻译】AppFuse 教程
- AppFuse 2.0 教程及相关文档翻译计划
- 使用Maven项目的appfuse插件构建 Struts2.0+Spring2.0+Hibernate项目
- CNTK API文档翻译(10)——使用LSTM预测时间序列数据
- CNTK API文档翻译(1)——使用数列
- CNTK API文档翻译(5)——对MNIST数据使用逻辑回归
- CNTK API文档翻译(6)——对MNIST数据使用多层感知机