Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
Articles
Articles_cn
Articles_pt
Articles_zh
CreateManager_zh
LeftMenu
SandBox




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateDAO_zh


Difference between version 23 and version 12:

At line 1 changed 1 line.
__Part I:__ [在AppFuse建立DAO和对象|CreateDAO_zh] - 一个建立对象(代表数据库的表)和把这些对象存储到数据库的Java类的教程。
__Part I:__ [在AppFuse建立DAO和POJO |CreateDAO_zh] - 一个建立对象(代表数据库的表)和把这些对象存储到数据库的Java类的教程。
At line 43 changed 1 line.
%%note __注意:__ 直接拷贝本教程的代码 [在FireFox下无效|http://raibledesigns.com/page/rd?anchor=java2html_plugin_for_jspwiki_causes],但我们可以通过CTRL+Click选定一个代码所在的工作区(OS X下是Command+Click),然后再拷贝。%%
%%note __注意:__ [不能在FireFox中|http://raibledesigns.com/page/rd?anchor=java2html_plugin_for_jspwiki_causes]直接拷贝本教程的代码 ,但我们可以通过CTRL+Click选定一个代码所在的工作区(OS X下是Command+Click),然后再拷贝。%%
At line 62 changed 1 line.
这个类必须扩展[BaseObject|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/model/BaseObject.java.html],而这个BaseObject有三个抽象方法(equals(), hashCode()和toString())需要你在Person类里实现,前两个是Hibernate的需要。为了完成这部分工作最简单的方式是使用[Commonclipse|http://commonclipse.sf.net],关于这个工具更多的信息可以在[Lee Grey的网站|http://www.leegrey.com/hmm/2004/09/29/1096491256000.html]里看到,另外一个你可以使用的Eclipse的插件是[Commons4E|http://commons4e.berlios.de/],我还没有使用过,这里不便对其功能作出评论。
这个类必须扩展[BaseObject|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/model/BaseObject.java.html],而这个BaseObject有三个抽象方法(equals(), hashCode()和toString())需要你在Person类里实现,前两个是Hibernate的需要。为了完成这部分工作最简单的方式是使用[Commonclipse|http://commonclipse.sf.net],关于这个工具更多的信息可以在[Lee Grey的站点|http://www.leegrey.com/hmm/2004/09/29/1096491256000.html]里看到,另外一个你可以使用的Eclipse的插件是[Commons4E|http://commons4e.berlios.de/],我还没有使用过,这里不便对其功能作出评论。
At line 93 changed 1 line.
;:%%(color: blue)''我使用{{generator-class="increment"}}而不使用{{generate-class="native"}} 是因为我对数据库使用"native"时[发现了一些问题|AppFuseOnDB2],如果你只是希望使用MySQL,__推荐使用"native"值__,本教程使用increment。''%%
;:%%(color: blue)''我使用{{generator-class="increment"}}而不使用{{generate-class="native"}} 是因为我对数据库使用"native"时[发现一些问题|AppFuseOnDB2],如果你只是希望使用MySQL,__推荐使用"native"值__,本教程使用increment。''%%
At line 181 changed 1 line.
现在,我们要创建一个DaoTest来测试我们的DAO的工作,“等会儿”,你说,“我们还不曾创建DAO呢!”,你说得对。无论如何,我发现[测试驱动开发|http://www.artima.com/intv/testdriven.html]大大的促进了软件质量,在许多年里我一直认为__在写代码之前写测试__是胡说八道,这看起来很愚蠢,但当我尝试之后我认为这样非常好,现在我按照测试驱动的方式工作完全因为我发现这样可以大大提高我软件开发的效率。
现在,我们要创建一个DaoTest来测试我们的DAO的工作,“等会儿”,你说,“我们还不曾创建DAO呢!”,你说得对。无论如何,我发现[测试驱动开发|http://www.artima.com/intv/testdriven.html]大大的促进了软件质量,在许多年里我一直认为__在写代码之前写测试__是胡说八道,这看起来很愚蠢,但当我尝试之后我认为这样非常好,现在我按照测试驱动的方式工作完全因为我发现这样可以大大提高我软件开发的效率。
At line 199 changed 3 lines.
protected void setUp() throws Exception {
super.setUp();
dao = (PersonDao) ctx.getBean("personDao");
public void setPersonDao(PersonDao dao) {
this.dao = dao;
At line 202 added 2 lines.
}
}]
At line 204 changed 3 lines.
protected void tearDown() throws Exception {
super.tearDown();
dao = null;
以上是我们使用JUnit测试而初始化和销毁PersonDao的基本代码,对象“ctx”引用了Spring的ApplicationContext,它在[BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDaoTestCase.java.html]类的静态代码区里被初始化。
现在我们需要实际测试DAO中的CRUD(create, retrieve, update, delete)方法,为此我们需要为每个方法建立以test(全部小写)开头的测试方法,只要这个方法是公共的,返回类型是void,它们就会被我们build.xml中的Ant的<junit>任务调用,如下是一些简单的CRUD测试,需要注意的一点是所有的方法(或者叫做测试)必须是自治的,添加如下代码到文件{{PersonDaoTest.java}}:
[{Java2HtmlPlugin
public void testGetPerson() throws Exception {
person = new Person();
person.setFirstName("Matt");
person.setLastName("Raible");
dao.savePerson(person);
assertNotNull(person.getId());
person = dao.getPerson(person.getId());
assertEquals(person.getFirstName(), "Matt");
At line 222 added 91 lines.
public void testSavePerson() throws Exception {
person = dao.getPerson(new Long(1));
person.setFirstName("Matt");
person.setLastName("Last Name Updated");
dao.savePerson(person);
if (log.isDebugEnabled()) {
log.debug("updated Person: " + person);
}
assertEquals(person.getLastName(), "Last Name Updated");
}
public void testAddAndRemovePerson() throws Exception {
person = new Person();
person.setFirstName("Bill");
person.setLastName("Joy");
dao.savePerson(person);
assertEquals(person.getFirstName(), "Bill");
assertNotNull(person.getId());
if (log.isDebugEnabled()) {
log.debug("removing person...");
}
dao.removePerson(person.getId());
try {
person = dao.getPerson(person.getId());
fail("Person found in database");
} catch (DataAccessException dae) {
log.debug("Expected exception: " + dae.getMessage());
assertNotNull(dae);
}
}
}]
;:%%(color: blue)''在testGetPerson方法,我们创建了一个person并且调用get方法,我通常会增加一条我所需要的记录到数据库,因为在测试运行之前[DBUnit|http://www.dbunit.org]会为数据库准备测试数据,我们可以简单的在metadata/sql/sample-data.xml里添加测试所必须的记录''%%
<div style="color: blue !important; margin-left: 50px">
{{{
<table name='person'>
<column>id</column>
<column>first_name</column>
<column>last_name</column>
<row>
<value>1</value>
<value>Matt</value>
<value>Raible</value>
</row>
</table>
}}}
</div>
;:%%(color: blue)''&#36890;&#36807;&#36825;&#31181;&#26041;&#24335;&#20320;&#21487;&#20197;&#22312;testGetPerson&#26041;&#27861;&#37324;&#28040;&#38500;&#21019;&#24314;&#26032;&#32426;&#24405;&#30340;&#21160;&#20316;&#65292;&#22914;&#26524;&#20320;&#24895;&#24847;&#30452;&#25509;&#25554;&#20837;&#35760;&#24405;&#21040;&#25968;&#25454;&#24211;&#65288;&#20351;&#29992;SQL&#25110;&#32773;GUI&#65289;&#65292;&#20320;&#21487;&#20197;&#29992;__ant db-export__&#21644;__cp {{db-export.xml metadata/sql/sample-data.xml}}__&#37325;&#26032;&#26500;&#24314;&#20320;&#30340;{{sample-data.xml}}&#25991;&#20214;&#12290;''%%
&#22312;&#19978;&#38754;&#30340;&#20363;&#23376;&#37324;&#65292;&#20320;&#21487;&#20197;&#30475;&#21040;&#25105;&#20204;&#35843;&#29992;person.set*(value)&#26469;&#20934;&#22791;&#25105;&#20204;&#38656;&#35201;&#20445;&#23384;&#30340;&#23545;&#35937;&#65292;&#22312;&#36825;&#20010;&#20363;&#23376;&#37324;&#24456;&#31616;&#21333;&#65292;&#20294;&#26159;&#24403;&#20320;&#35201;&#25554;&#20837;10&#26465;&#24517;&#28155;&#23383;&#27573;(not-null="true")&#26102;&#23601;&#27604;&#36739;&#40635;&#28902;&#20102;&#65292;&#36825;&#23601;&#26159;&#25105;&#20026;&#20160;&#20040;&#35201;&#22312;BaseDaoTestCase&#20351;&#29992;ResourceBundle&#25991;&#20214;&#65292;&#21482;&#35201;&#22312;{{PersonDaoTest.java}}&#21516;&#19968;&#20010;&#30446;&#24405;&#21019;&#24314;&#19968;&#20010;{{PersonDaoTest.properties}}&#24182;&#19988;&#22312;&#37324;&#38754;&#23450;&#20041;&#20320;&#30340;&#23646;&#24615;&#20540;&#65306;
;:%%(color: blue)''&#25105;&#36890;&#24120;&#21482;&#26159;&#22312;Java&#37324;&#30828;&#32534;&#30721;&#65292;&#20294;&#26159;&#36825;&#20010;.properties&#23545;&#20110;&#22823;&#23545;&#35937;&#24456;&#26377;&#29992;&#12290;''%%
{{{
firstName=Matt
lastName=Raible
}}}
&#27492;&#26102;&#65292;&#20320;&#35201;&#36890;&#36807;&#35843;&#29992;BaseDaoTestCase.populate(java.lang.Object)&#26041;&#27861;&#26469;&#20934;&#22791;&#23545;&#35937;&#65292;&#32780;&#19981;&#26159;&#20351;&#29992;person.set*&#12290;
[{Java2HtmlPlugin
person = new Person();
person = (Person) populate(person);
}]
&#22312;&#30446;&#21069;&#24773;&#20917;&#19979;&#65292;&#36824;&#19981;&#21487;&#20197;&#32534;&#35793;PersonDaoTest&#65292;&#22240;&#20026;&#22312;&#31867;&#36335;&#24452;&#37324;&#36824;&#27809;&#26377;PersonDao.class&#65292;&#25105;&#20204;&#38656;&#35201;&#21019;&#24314;&#23427;&#12290;PersonDao.java&#26159;&#19968;&#20010;&#25509;&#21475;&#65292;PersonDaoHibernate.java&#26159;&#23427;&#30340;Hibernate&#23454;&#29616;&#65292;&#35753;&#25105;&#20204;&#32487;&#32493;&#65292;&#24320;&#22987;&#21019;&#24314;&#12290;
!!&#21019;&#24314;&#19968;&#20010;&#23545;&#23545;&#35937;&#25191;&#34892;CRUD&#25805;&#20316;&#30340;&#26032;DAO[#4]
&#39532;&#19978;&#65292;&#22312;{{src/dao/**/dao}}&#30446;&#24405;&#37324;&#24314;&#31435;PersonDao.java&#25509;&#21475;&#65292;&#24182;&#19988;&#25351;&#23450;&#25152;&#26377;&#23454;&#29616;&#31867;&#35201;&#23454;&#29616;&#30340;&#22522;&#26412;CRUD&#25805;&#20316;&#65292;&#20026;&#20102;&#26174;&#31034;&#26041;&#20415;&#65292;&#25105;&#24050;&#32463;&#21435;&#25481;&#20102;&#25152;&#26377;JavaDocs&#12290;
[{Java2HtmlPlugin
package org.appfuse.dao;
import org.appfuse.model.Person;
public interface PersonDao extends Dao {
public Person getPerson(Long personId);
public void savePerson(Person person);
public void removePerson(Long personId);
At line 315 added 77 lines.
&#27880;&#24847;&#65292;&#22312;&#20197;&#19978;&#30340;&#26041;&#27861;&#22768;&#26126;&#19978;&#24182;&#27809;&#26377;exceptions&#35828;&#26126;&#65292;&#36825;&#26159;&#22240;&#20026;[Spring|http://www.springframework.org]&#20351;&#29992;RuntimeExceptions&#26469;&#21253;&#35065;Exceptions&#30340;&#26041;&#24335;&#65292;&#27492;&#26102;&#65292;&#20320;&#24050;&#32463;&#21487;&#20197;&#20351;&#29992;__ant compile-dao__&#26469;&#32534;&#35793;{{src/dao}}&#21644;{{test/dao}}&#19979;&#30340;&#25152;&#26377;&#28304;&#25991;&#20214;&#65292;&#28982;&#32780;&#24403;&#20320;&#36816;&#34892;__ant test-dao -Dtestcase=PersonDao__&#36827;&#34892;&#27979;&#35797;&#26102;&#65292;&#20320;&#20250;&#24471;&#21040;&#19968;&#20010;&#38169;&#35823;&#65306;<span style="color: red">No bean named 'personDao' is defined</span>&#65292;&#36825;&#26159;&#19968;&#20010;Spring&#30340;&#38169;&#35823;&#65292;&#35828;&#26126;&#20320;&#24517;&#39035;&#22312;{{applicationContext-hibernate.xml}}&#25351;&#23450;&#19968;&#20010;&#21517;&#23383;&#20026;''personDAO''&#30340;bean&#65292;&#22312;&#27492;&#20043;&#21069;&#25105;&#20204;&#38656;&#35201;&#21019;&#24314;PersonDao&#30340;&#23454;&#29616;&#31867;&#12290;
;:''&#36816;&#34892;dao&#27979;&#35797;&#30340;ant&#20219;&#21153;&#21483;&#20570;__test-dao__&#65292;&#22914;&#26524;&#20320;&#20256;&#36882;testcase&#21442;&#25968;(&#29992;__-Dtestcase=name__)&#65292;&#23427;&#20250;&#26597;&#30475;{{**/*${testcase}*}}&#20801;&#35768;&#25105;&#20204;&#20256;&#36882;Person&#12289;PersonDao&#12289;&#25110;&#32773;PersonDaoTest&#20197;&#21450;&#25152;&#26377;&#20250;&#25191;&#34892;PersonDaoTest&#30340;&#31867;&#12290;''
&#35753;&#25105;&#20204;&#21019;&#24314;&#19968;&#20010;&#23454;&#29616;PersonDao&#30340;&#31867;PersonDaoHibernate&#24182;&#20351;&#29992;Hibernate&#26469;get/save/delete&#36825;&#20010;Person&#23545;&#35937;&#65292;&#20026;&#27492;&#65292;&#25105;&#20204;&#22312;{{src/dao/**/dao/hibernate}}&#21019;&#24314;&#19968;&#20010;&#26032;&#31867;{{PersonDaoHibernate.java}}&#65292;&#23427;&#24212;&#35813;&#25193;&#23637;[BaseDaoHibernate|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDAOHibernate.java.html]&#65292;&#24182;&#19988;&#23454;&#29616;PersonDao&#12290;''&#20026;&#20102;&#31616;&#27905;&#65292;&#30465;&#30053;Javadocs&#12290;''
[{Java2HtmlPlugin
package org.appfuse.dao.hibernate;
import org.appfuse.model.Person;
import org.appfuse.dao.PersonDao;
import org.springframework.orm.ObjectRetrievalFailureException;
public class PersonDaoHibernate extends BaseDaoHibernate implements PersonDao {
public Person getPerson(Long id) {
Person person = (Person) getHibernateTemplate().get(Person.class, id);
if (person == null) {
throw new ObjectRetrievalFailureException(Person.class, id);
}
return person;
}
public void savePerson(Person person) {
getHibernateTemplate().saveOrUpdate(person);
}
public void removePerson(Long id) {
// object must be loaded before it can be deleted
getHibernateTemplate().delete(getPerson(id));
}
}
}]
&#29616;&#22312;&#65292;&#22914;&#26524;&#20320;&#36816;&#34892;__ant test-dao -Dtestcase=PersonDao__&#65292;&#20320;&#20250;&#24471;&#21040;&#21516;&#26679;&#30340;&#38169;&#35823;&#65292;&#25105;&#20204;&#24517;&#39035;&#37197;&#32622;Spring&#26469;&#35753;&#23427;&#30693;&#36947;PersonDaoHibernate&#26159;PersonDao&#30340;&#23454;&#29616;&#65292;&#21516;&#26679;&#30340;&#65292;&#25105;&#20204;&#20063;&#35201;&#21578;&#35785;&#23427;&#36824;&#26377;&#20010;Person&#23545;&#35937;&#12290;
!!&#37197;&#32622;Spring&#20013;&#30340;Person&#21644;PersonDao [#5]
&#39318;&#20808;&#25105;&#20204;&#35201;&#21578;&#35785;Spring&#25152;&#26377;Hibernate&#25991;&#20214;&#30340;&#20301;&#32622;&#65292;&#20026;&#27492;&#65292;&#25171;&#24320;{{src/dao/**/dao/hibernate/applicationContext-hibernate.xml}}&#65292;&#22312;&#20197;&#19979;&#20195;&#30721;&#22359;&#28155;&#21152;{{"Person.hbm.xml"}}&#12290;
[{Java2HtmlPlugin
<property name="mappingResources">
<list>
<value>org/appfuse/model/Person.hbm.xml</value>
<value>org/appfuse/model/Role.hbm.xml</value>
<value>org/appfuse/model/User.hbm.xml</value>
</list>
</property>
}]
&#29616;&#22312;&#25105;&#20204;&#38656;&#35201;&#28155;&#21152;&#19968;&#20123;XML&#25968;&#25454;&#26469;&#32465;&#23450;PersonDaoHibernate&#21040;PersonDao&#65292;&#20026;&#27492;&#65292;&#28155;&#21152;&#22914;&#19979;&#20195;&#30721;&#21040;&#25991;&#20214;&#24213;&#37096;&#65306;
[{Java2HtmlPlugin
<!-- PersonDao: Hibernate implementation -->
<bean id="personDao" class="org.appfuse.dao.hibernate.PersonDaoHibernate">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
}]
;:''&#20320;&#20063;&#21487;&#20197;&#20026;&lt;bean&gt;&#20351;&#29992;__autowire="byName"__&#23646;&#24615;&#26469;&#28040;&#38500;"sessionFactory"&#23646;&#24615;''&#12290;%%(color: blue)''&#20174;&#20010;&#20154;&#26469;&#35762;&#65292;&#25105;&#21916;&#27426;&#22312;XML&#25991;&#20214;&#37324;&#20445;&#30041;&#23545;&#35937;&#30340;&#20381;&#36182;&#12290;''%%
!!&#36816;&#34892;DaoTest[#6]
&#20445;&#23384;&#25152;&#26377;&#20462;&#25913;&#30340;&#25991;&#20214;&#65292;&#36816;&#34892;__ant test-dao -Dtestcase=PersonDao__&#12290;
__Yeah Baby, Yeah:__
%%(color:green)BUILD SUCCESSFUL\\
Total time: 9 seconds%%
----
''&#19979;&#19968;&#37096;&#20998;:'' __Part II:__ [创建新的Manager|CreateManager_zh] - &#26159;&#19968;&#20010;&#24314;&#31435;&#31867;&#20284;&#20110;[Session Facades|http://java.sun.com/blueprints/patterns/SessionFacade.html]&#30340;&#65292;&#20294;&#19981;&#20351;&#29992;EJBs&#30340;&#19994;&#21153;Facade&#35828;&#26126;&#65292;&#36825;&#20010;facades&#29992;&#26469;&#24314;&#31435;&#20174;&#21069;&#31471;&#21040;DAO&#23618;&#30340;&#32852;&#31995;&#12290;

Back to CreateDAO_zh, or to the Page History.