??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品国产九九九,欧美成人一级视频,一区二区亚洲精品http://www.aygfsteel.com/cader/category/12840.html要想负多生孩子少U树zh-cnFri, 02 Mar 2007 02:42:41 GMTFri, 02 Mar 2007 02:42:41 GMT60CreateDAO_zhhttp://www.aygfsteel.com/cader/articles/57003.html负h博客负h博客Thu, 06 Jul 2006 09:53:00 GMThttp://www.aygfsteel.com/cader/articles/57003.htmlhttp://www.aygfsteel.com/cader/comments/57003.htmlhttp://www.aygfsteel.com/cader/articles/57003.html#Feedback0http://www.aygfsteel.com/cader/comments/commentRss/57003.htmlhttp://www.aygfsteel.com/cader/services/trackbacks/57003.html Part I: 在AppFuse建立DAO和对象 - 一个徏立对?代表数据库的?和把q些对象存储到数据库的Javacȝ教程?

关于本教E?/h3>本教E将向你展示如何在一个数据库里创Q以及如何完成访问这些表的Java代码?

我们徏立一个对象以及处理(保存/?删除Q这些类到数据库的一些代码。用Java术语Q我们叫它Plain Old Java Object(a.k.a. a POJO)。这个对象通常代表了数据库中的一个表Q?i>其他的类包括:

  • 一个数据访问对象Data Access Object (a.k.a. a DAO), 一?Interface和一个Hibernate实现
  • 一?JUnit cL试我们的DAO对象
NOTE: 如果你用MySQLq且希望使用事务 (很有可能是这个情?,你需要用InnoDB tablesQؓ了做到这一? d以下两句话到 (/etc/my.cnf 或?c:\Windows\my.ini)?其中W二个设|?(讄使用UTF-8字符)?.1.7+所必需的?
[mysqld]
default-table-type=innodb
default-character-set=utf8
如果你用PostgreSQLq且在成批处理时得到许多qh的错误,试着把关闭它Q方法是增加 <prop key="hibernate.jdbc.batch_size">0</prop> C?src/dao/**/hibernate/applicationContext-hibernate.xml文g?

AppFuse使用Hibernate 作ؓ持久化层Q?Hibernate是一套对?关系Object/Relational (O/R)框架Q他允许你把Java对象和数据库之间联系hQ它可以很方便的对你的对象执行CRUD (Create, Retrieve, Update, Delete)操作?

你也可以选择使用iBATIS作ؓ持久化层Q如果要在AppFuse里安装iBATISQ?h?tt>extras/ibatis中的README.txt。如果你选择iBATIS而不是HibernateQ?希望你有自己的原因ƈ且熟(zhn)这个框Ӟ我也希望你能够领会到如何教E应用到iBATIS ;-)

字体惯例 (q行?

要在命o行下执行的命令是q个样子: ant test-all.
对目录或者包中的文g的引用是q个样子: build.xml.
我在“(lin)真实世界”中实际操作的方式用蓝色斜体表C?/i>

让我们l在AppFuse目的结构下创徏一个新的对象、DAO和测试?

目录

  • [1] 建立一个对象,q且?a class="external" >XDoclet标记
  • [2] 使用AntҎ(gu)对象建立数据库中的表
  • [3] 创徏一个DaoTest来运行DAO对象的JUnit试
  • [4] 创徏一个新的DAO来执行关于这个对象的CRUD操作
  • [5] 在spring里配|Person和PersonDao
  • [6] q行DaoTest

建立一个对象,q且作XDoclet标记 [#1]

我们要做的第一件事情就是徏立一个需要持久化的对象,我们要在src/dao/**/model目录下徏立一个简单的Person对象Q这个对象包括id、firstName和lastName属性?

注意Q?/b> 直接拯本教E的代码 &#22312;FireFox&#19979;&#26080;&#25928;Q但我们可以通过CTRL+Click选定一个代码所在的工作?OS X下是Command+Click)Q然后再拯?/span>


package org.appfuse.model;

public class Person extends BaseObject {
    private Long id;
    private String firstName;
    private String lastName;

    /*
     Generate your getters and setters using your favorite IDE: 
     In Eclipse:
     Right-click -> Source -> Generate Getters and Setters
    */
}

q个cdL?a class="external" >BaseObjectQ而这个BaseObject有三个抽象方?equals(), hashCode()和toString())需要你在Personc里实现Q前两个是Hibernate的需要。ؓ了完成这部分工作最单的方式是?a class="external" >CommonclipseQ关于这个工h多的信息可以?a class="external" >Lee Grey&#30340;&#32593;&#31449;里看刎ͼ另外一个你可以使用的Eclipse的插件是Commons4EQ我q没有用过Q这里不便对其功能作论?

如果你?a class="external" >IntelliJ IDEAQ你可以自动产生equals()和hashCode()Q但没有toString()Q有一?ToStringPlugin插g做得非常不错

现在我们已经创徏了这个POJO对象Q我们需要增加XDoclet标记来生Hibernate的映文Ӟq些文g用来映射对象?表和属?变量) ?字段?

首先Q我们增?a class="external" >@hibernate.class 来告诉Hibernate我们要和那个表作关联:


/**
 * @hibernate.class table="person"
 */
public class Person extends BaseObject {

我们也要增加主键的映?否则XDoclet会在产生映射文g时出?注意所有的@hibernate.*标签必须?b>getters'的Javadocs里面?


    /**
     @return Returns the id.
     * @hibernate.id column="id"
     *  generator-class="increment" unsaved-value="null"
     */

    public Long getId() {
        return this.id;
    }

我?tt>generator-class="increment"而不使用generate-class="native" 是因为我Ҏ(gu)据库使用"native"?a class="wikipage" ?/b>Q本教程使用increment?/i>

使用AntҎ(gu)对象产生数据库表[#2]

在这U情况下,你可以通过q行ant setup-db来徏立person表,q个d会生文?tt>Person.hbm.xmlq且会徏立叫?person"的表Q从Ant的控制台H口Q你可以看到HibernateZ建立的表l构的内宏V?
[schemaexport] create table person (
[schemaexport]    id bigint not null,
[schemaexport]    primary key (id)
[schemaexport] );

如果你查看Hibernate生成的文?tt>Person.hbm.xmlQ可以到build/dao/gen/**/model目录Q这里是Person.hbm.xml的内?目前的内?:


<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
    <class
        name="org.appfuse.model.Person"
        table="person"
        dynamic-update="false"
        dynamic-insert="false"
    >

        <id
            name="id"
            column="id"
            type="java.lang.Long"
            unsaved-value="null"
        >
            <generator class="increment">
            </generator>
        </id>

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Person.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>

现在我们要ؓ其它的字D?first_name, last_name)d额外?a class="external" >@hibernate.property标签Q?


    /**
     * @hibernate.property column="first_name" length="50"
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * @hibernate.property column="last_name" length="50"
     */
    public String getLastName() {
        return this.lastName;
    }

在这个例子里Q添?i>column属性的唯一原因是因个字D名与它的属性名不相同,如果他们相同Q你没有必要来指?i>column属性,关于其它可以使用的标{请?a class="external" >@hibernate.property?

再次q行ant setup-db把新加的属性加到数据库表里?

[schemaexport] create table person (
[schemaexport]    id bigint not null,
[schemaexport]    first_name varchar(50),
[schemaexport]    last_name varchar(50),
[schemaexport]    primary key (id)
[schemaexport] );

如果期望修改字段的长度,修改@hibernate.property标签?i>length属性,如果希望把字D|为必dD?NOT NULL)Q可以增加属性not-null="true"?

建立新的DaoTest来对你的DAOq行JUnit试[#3]

注意:从Appfuse版本1.6.1+开始包括了一?a class="wikipage" >AppGen工具Q可以用来生成本教程余下的所有的cȝ代码Q不q,我们最好还是先q一遍教E再使用q个工具产生代码?/span>

现在Q我们要创徏一个DaoTest来测试我们的DAO的工作,“(lin){会儿”,你说Q?lin)我们还不曾创徏DAO呢!”Q你说得寏V无论如何,我发?a class="external" >&#27979;&#35797;&#39537;&#21160;&#24320;&#21457;大大的促q了软g质量Q在许多q里我一直认?b>在写代码之前写测?/b>是胡说八道,q看h很愚蠢,但当我尝试之后我认ؓq样非常好,现在我按照测试驱动的方式工作完全因ؓ我发现这样可以大大提高我软g开发的效率?

开始,我们?tt>test/dao/**/dao目录下徏立类PersonDaoTest.javaQ这个类必须扩展BaseDaoTestCaseQ而BaseDAOTestCaseq个cLJUnitc?a class="external" >TestCase的子c,q个cȝ来加?a class="external" >Spring的ApplicationContextQ因为Spring把各个层l定Q和单元试cd一目录下同你的试cL件同名的.properties文gQResourceBundleQ,q个属性文件的属性可以通过“(lin)rb”属性来讉K?

我经常拷?打开→另存ؓ)一个已存在的测?如UserDaoTest.java)Q然后查?替换 [Uu]ser为[Pp]ersonQ或者Q何其它需要替换的内容?/i>


package org.appfuse.dao;

import org.appfuse.model.Person;
import org.springframework.dao.DataAccessException;

public class PersonDaoTest extends BaseDaoTestCase {
    
    private Person person = null;
    private PersonDao dao = null;

    public void setPersonDao(PersonDao dao) {
        this.dao = dao;
    }
}

以上是我们用JUnit试而初始化和销毁PersonDao的基本代码,对象“(lin)ctx”引用了Spring的ApplicationContextQ它?a class="external" >BaseDaoTestCasecȝ静态代码区里被初始化?

现在我们需要实际测试DAO中的CRUD(create, retrieve, update, delete)Ҏ(gu)Qؓ此我们需要ؓ每个Ҏ(gu)建立以testQ全部小写)开头的试Ҏ(gu)Q只要这个方法是公共的,q回cd是void,它们׃被我们build.xml中的Ant?lt;junit>d调用Q如下是一些简单的CRUD试Q需要注意的一Ҏ(gu)所有的Ҏ(gu)Q或者叫做测试)必须是自ȝQ添加如下代码到文gPersonDaoTest.javaQ?


    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");
    }

    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);
        }
    }

在testGetPersonҎ(gu)Q我们创Z一个personq且调用getҎ(gu)Q我通常会增加一条我所需要的记录到数据库Q因为在试q行之前DBUnit会ؓ数据库准备测试数据,我们可以单的在metadata/sql/sample-data.xml里添加测试所必须的记?/i>

<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>
通过q种方式你可以在testGetPersonҎ(gu)里消除创建新U录的动作,如果你愿意直接插入记录到数据库(使用SQL或者GUIQ,你可以用ant db-export?b>cp db-export.xml metadata/sql/sample-data.xml重新构徏你的sample-data.xml文g?/i>

在上面的例子里,你可以看到我们调用person.set*(value)来准备我们需要保存的对象Q在q个例子里很单,但是当你要插?0条必dD?not-null="true")时就比较ȝ了,q就是我Z么要在BaseDaoTestCase使用ResourceBundle文gQ只要在PersonDaoTest.java同一个目录创Z?tt>PersonDaoTest.propertiesq且在里面定义你的属性|

我通常只是在Java里硬~码Q但是这?properties对于大对象很有用?/i>
firstName=Matt
lastName=Raible
此时Q你要通过调用BaseDaoTestCase.populate(java.lang.Object)Ҏ(gu)来准备对象,而不是用person.set*?


person = new Person();
person = (Personpopulate(person);

在目前情况下Q还不可以编译PersonDaoTestQ因为在c\径里q没有PersonDao.classQ我们需要创建它。PersonDao.java是一个接口,PersonDaoHibernate.java是它的Hibernate实现Q让我们l箋Q开始创建?

创徏一个对对象执行CRUD操作的新DAO[#4]

马上Q在src/dao/**/dao目录里徏立PersonDao.java接口Qƈ且指定所有实现类要实现的基本CRUD操作Qؓ了显C方便,我已l去掉了所有JavaDocs?


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);
}

注意Q在以上的方法声明上q没有exceptions说明Q这是因?a class="external" >Spring使用RuntimeExceptions来包裹Exceptions的方式,此时Q你已经可以使用ant compile-dao来编?tt>src/dao?tt>test/dao下的所有源文gQ然而当你运?b>ant test-dao -Dtestcase=PersonDaoq行试Ӟ你会得到一个错误:No bean named 'personDao' is definedQ这是一个Spring的错误,说明你必dapplicationContext-hibernate.xml指定一个名字ؓpersonDAO的beanQ在此之前我们需要创建PersonDao的实现类?

q行dao试的antd叫做test-daoQ如果你传递testcase参数(?b>-Dtestcase=name)Q它会查?tt>**/*${testcase}*允许我们传递Person、PersonDao、或者PersonDaoTest以及所有会执行PersonDaoTest的类?/i>

让我们创Z个实现PersonDao的类PersonDaoHibernateq用Hibernate来get/save/deleteq个Person对象Qؓ此,我们?tt>src/dao/**/dao/hibernate创徏一个新c?tt>PersonDaoHibernate.javaQ它应该扩展BaseDaoHibernateQƈ且实现PersonDao?i>Zz,省略Javadocs?/i>


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 = (PersongetHibernateTemplate().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));
    }
}

现在Q如果你q行ant test-dao -Dtestcase=PersonDaoQ你会得到同L错误Q我们必配|Spring来让它知道PersonDaoHibernate是PersonDao的实玎ͼ同样的,我们也要告诉它还有个Person对象?

配置Spring中的Person和PersonDao [#5]

首先我们要告诉Spring所有Hibernate文g的位|,为此Q打开src/dao/**/dao/hibernate/applicationContext-hibernate.xmlQ在以下代码块添?tt>"Person.hbm.xml"?


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

现在我们需要添加一些XML数据来绑定PersonDaoHibernate到PersonDaoQؓ此,d如下代码到文件底部:


<!-- PersonDao: Hibernate implementation --> 
<bean id="personDao" class="org.appfuse.dao.hibernate.PersonDaoHibernate"
    <property name="sessionFactory"><ref local="sessionFactory"/></property> 
</bean> 

你也可以?lt;bean>使用autowire="byName"属性来消除"sessionFactory"属?/i>?span style="COLOR: blue">从个人来Ԍ我喜Ƣ在XML文g里保留对象的依赖?/i>

q行DaoTest[#6]

保存所有修改的文gQ运?b>ant test-dao -Dtestcase=PersonDao?

Yeah Baby, Yeah:BUILD SUCCESSFUL
Total time: 9 seconds


下一部分:Part II:&#21019;&#24314;&#31649;&#29702;&#22120;Manager - 是一个徏立类gSession Facades的,但不使用EJBs的业务Facade说明Q这个facades用来建立从前端到DAO层的联系?



负h博客 2006-07-06 17:53 发表评论
]]>
վ֩ģ壺 ƽ| ɽ| | ƽ| Ƹ| | | ˮ| | | | | | κ| Ž| ƽ| | ϴ| Դ| ݸ| Ҫ| ϳ| Դ| ̩| ǭ| | ԰| IJ| | ɽ| | »| Ǭ| Ͻ| пѷ| | Ϋ| | | | |