Thursday, August 31, 2006
Generic CRUD DAO
這是參考Don't repeat the DAO!這篇文章前面一部分的note
單純運用Java 5.0 Generic、Spring、Hibernate
後面還有加入AOP的部份比較複雜
改天我再另外整理
這篇文章的程式碼
為Eclipse Project,需要的library都放好在裡面了,測試請以Unit Test執行PersonDaoTest.java
Generic CRUD DAO
Generic CRUD DAO只需要
GenericDaointerfaceGenericDaoHibernateImplclass
GenericDao.java
package genericdao;
import java.io.Serializable;
public interface GenericDao<T, PK extends Serializable> {
PK create(T newInstance);
T read(PK id);
void update(T transientObject);
void delete(T persistentObject);
}
GenericDaoHibernateImpl.java
package genericdao.impl;
import genericdao.GenericDao;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
public class GenericDaoHibernateImpl<T, PK extends Serializable> implements GenericDao<T, PK> {
private SessionFactory sessionFactory;
private Class<T> type;
public GenericDaoHibernateImpl(Class<T> type) {
this.type = type;
}
public PK create(T o) {
return (PK) getSession().save(o);
}
public T read(PK id) {
return (T) getSession().get(type, id);
}
public void update(T o) {
getSession().update(o);
}
public void delete(T o) {
getSession().delete(o);
}
public Session getSession() {
boolean allowCreate = true;
return SessionFactoryUtils.getSession(sessionFactory, allowCreate);
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Your DAO
使用Generic CRUD DAO來寫你自己的CRUD DAO你需要
- Your Domain Object
- Your Domain Object's Hibernate Mapping
Person.java (Your Domain Object)
package genericdaotest.domain;
import java.io.Serializable;
public class Person implements Serializable {
private Long id;
private String name;
private Integer weight;
public Person(String name, Integer weight) {
this.name = name;
this.weight = weight;
}
// Default constructor needed by Hibernate
protected Person() {
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
}
Person.hbm.xml (Your Domain Object's Hibernate Mapping)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="genericdaotest.domain">
<class name="Person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" update="false" />
<property name="weight" />
</class>
</hibernate-mapping>
Use Your DAO
使用你的DAO需要
- Spring Configuration File
- Codes That Use Your DAO
my-test.xml (Spring Configration File)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:file:db/data</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>genericdaotest/domain/Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="personDao"
class="genericdao.impl.GenericDaoHibernateImpl">
<constructor-arg>
<value>genericdaotest.domain.Person</value>
</constructor-arg>
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
</beans>
PersonDaoTest.java (Codes That Use Your DAO)
package genericdaotest;
import genericdao.GenericDao;
import genericdaotest.domain.Person;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class PersonDaoTest extends TestCase {
private ApplicationContext factory;
public PersonDaoTest(String s) {
super(s);
factory = new ClassPathXmlApplicationContext("my-test.xml");
}
public void testCrud() throws Exception {
// Create
GenericDao personDao = (GenericDao) factory.getBean("personDao");
Person createPerson = new Person("Mellqvist", 88);
personDao.create(createPerson);
assertNotNull(createPerson.getId());
Long id = createPerson.getId();
restartSession();
// Read
Person foundPerson = (Person) personDao.read(id);
assertEquals(createPerson.getWeight(), foundPerson.getWeight());
restartSession();
// Update
Integer updateWeight = 90;
foundPerson.setWeight(updateWeight);
personDao.update(foundPerson);
Person updatedPerson = (Person) personDao.read(id);
assertEquals(updateWeight, updatedPerson.getWeight());
restartSession();
// Delete
personDao.delete(updatedPerson);
restartSession();
assertNull(personDao.read(id));
}
protected void setUp() throws Exception {
openSession();
}
protected void tearDown() throws Exception {
closeSession();
}
private void openSession() {
SessionFactory sessionFactory = getSessionFactory();
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory,
new SessionHolder(session));
}
private void closeSession() {
SessionFactory sessionFactory = getSessionFactory();
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
.unbindResource(sessionFactory);
sessionHolder.getSession().flush();
sessionHolder.getSession().close();
SessionFactoryUtils.releaseSession(sessionHolder.getSession(),
sessionFactory);
}
private void restartSession() {
closeSession();
openSession();
}
private SessionFactory getSessionFactory() {
return (SessionFactory) factory.getBean("sessionFactory");
}
}
Exercise
練習寫一個你自己的DAO看看吧!
還記得需要哪些檔案嗎?
你可以重用:
GenericDaointerfaceGenericDaoHibernateImplclass
- Your Domain Object
- Your Domain Object's Hibernate Mapping
- Spring Configuration File
- Codes That Use Your DAO




