Persistence - shenliuyang/development GitHub Wiki
h1. Persistence
Persistence部分的练习会创建一个新的数据对象(数据库表),创建一系列存取它的Java源代码文件。
你将创建一个对象,以及一系列负责与数据库交互,持久化这个对象的类。在Java的术语中,这样的一个对象就是POJO(Plain Old Java Object),这个对象基本上可以代表数据库中的一张表,在tutorial中,有通用的泛型实现的基础DAO和Manager,基本的Dao实现了CRUD的几乎所有操作,只有当你需要用到一些复杂的数据存取操作时,才需要自定义DAO和相应的方法实现。
tutorial使用JPA作为持久层,使用了Hibernate的实现,POJO可关联到数据库的表,允许你以面向对象的方式处理,很容易进行数据对象的处理(CRUD)。
为了在tutorial工程结构中,开始创建一个新的数据对象,请完成以下几步
h2. 创建一个新的POJO,增加JPA的Annotaton
创建一个简单的Person对象,放在src/main/java/**/entity目录下,创建两个属性,firstName, lastName,
public class Person extends IdEntity { private String firstName; private String lastName; /** 用IDE生成Getter和Setter方法,以Eclipse为例,Right-click->Source->Generate Setters And Getters 用你的IDE生成toString(), hashCode() and equals() methods: Eclipse: Right-click -> Source -> Generate toString(), hashCode(), equals() */ }
扩展IdEntity是可选的,IdEntity实现了自动增长的Id策略,目前多数对应的数据库的表适用于这种ID策略, 作为推荐,同时实现toString(), equals(), hashCode()方法. 如果你打算把这个数据对象放入用户的Session中,或者通过WebService直接传递它,也应该实现Serializable接口。
当生成equals和hashCode方法时, 不要包括你的对象主键。可以参考Hibernate手册中 "Equals and Hashcode":https://community.jboss.org/wiki/EqualsAndHashCode 的说明.
首先, 添加一个@Entity的注解, 这标记了关联的表。 "name"属性是可选的; 如果未定义将使用类名. 确保你添加了 "import annotations from javax.persistence.*", 而不是导入了Hibernate的Entity.
@Entity public class Person extends IdEntity {
可以使用@Table的Annotation改变对应到数据库的表名
@Entity @Table(name = "xx_person") public class Person extends IdEntity {
对于属性,在以下两种情况下要使用注解:
@Column(name="first_name", length=50) public String getFirstName() { return this.firstName; } ... @Column(name="last_name", length=50) public String getLastName() { return this.lastName; }
- 避免在属性上加注解: 要注意, 属性上加注解会覆盖掉getter方法上的,在这里,我们保持在getters方法上加注解的风格.
h2. 创建数据库表
现在可以来说说怎么创建对应的数据库表了,其实你几乎什么都不需要做,在tutorial的工程里会自动创建的,在这里解释一下,免得引起疑惑。
在tutorial中使用了maven的配置,结合Hibernate的plugin,为xxx-bean中带有Entity标记的POJO在构建过程中自动创建对应的数据库表,通过maven, hibernate, spring, dbunit, junit等等工具,大大的简化了开发,单元测试的工作,规范化了流程,有兴趣的可以以后多关注一下这方面的配置知识。
如果你真的自己动手敲完了所有的代码,并且明白了此节主要内容,请看下一章节 "创建PersonDao":http://redmine.appdot.org/redmine/projects/dev-center/wiki/CreateDao
h2. 创建PersonDaoTest
在创建PersonDao之前先创建PersonDaoTest,这种方式就叫做Test-Driven Development(测试驱动开发),这种方式更易于开发出高质量的软件,尝试一下,这会让我们受益良多。
首先,我们要创建一个PersonDaoTest.java的文件,放于在src/test/java/**/dao的目录,这个类继承自BaseDaoJpaTestCase,这个基类帮你加载了所需的所有SpringContext,方便你编写单元测试的代码。
/** * PersonDao的测试用例, 测试ORM映射及特殊的DAO操作. * * 默认在每个测试函数后进行回滚. * * @author liand */ public class PersonDaoTest extends BaseJpaDaoTestCase { @Autowired private PersonDao entityDao; @Test //如果你需要真正插入数据库,将Rollback设为false //@Rollback(false) public void crudEntityWithRole() { //新建并保存带权限组的用户 Person person = new Person(); person.setFirstName("testFirstName"); person.setLastName("testLastName"); entityDao.save(person); flush(); //获取用户 person = entityDao.findOne(person.getId()); assertEquals("testLastName", person.getLastName()); assertEquals("testFirstName", person.getFirstName()); //删除用户 entityDao.delete(person.getId()); flush(); person = entityDao.findOne(person.getId()); assertNull(person); } @Test public void testFindPersonByFirstName() throws Exception { List people = entityDao.findByFirstName("Lian"); assertTrue(people.size() > 0); } }
上面是一个实现了PersonDao的基本CRUD测试的单元测试用例,实际使用的测试用例会有更多的测试方法,但上面这个基本的测试用例可以帮助我们快速理解这个过程。
你应该注意到了,测试用例中使用了预置的数据,因为appdot建立的工程中集成了DbUnit的支持,因此还可以使用预定义的数据,DbUnit的Maven插件会在测试运行前建立数据库,灌入预置的数据,你只需要简单的编辑tutorial-data模块下的src/test/resources/sample-data.xml文件,就可由maven完成一整套自动化的流程。
h2. 创建PersonDao
在创建PersoDao这一节,你会发现无比的简单,基本上你只需要定义一个PersonDao的接口,继承支持泛型的BaseJpaRepository
/** * 人对象的Dao interface. * * @author liand */ public interface PersonDao extends IdEntityRepository {
这样你就拥有了支持基本CRUD操作的PersonDao,如果你需要使用更多的finders(查询方法),你只需要在接口中定义附加的方法
/** * 人对象的Dao interface. * * @author liand */ public interface PersonDao extends IdEntityRepository { List findByFirstName(String firstName); }
不需要再做任何实现,即可拥有findByFirstName,这一切源于我们使用了spring-data-jpa,不仅简单的查询,复杂的组合查询也同样能够实现,它是通过接口中定义的方法的名字,使用习惯大于配置的思想实现的,具体可参考spring-data-jpa的手册。
这可以将我们从书写无聊的sql中解脱出来,当然也同样支持自定义的实现,在spring-data-jpa中有自定义实现的完整参考,此处暂时不做赘述。
h2. 运行PersonDaoTest
使用"mvn test -Dtest=PersonDaoTest"尝试运行你上面敲出来的单元测试吧。