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只需要
GenericDao
interfaceGenericDaoHibernateImpl
class
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看看吧!
還記得需要哪些檔案嗎?
你可以重用:
GenericDao
interfaceGenericDaoHibernateImpl
class
- Your Domain Object
- Your Domain Object's Hibernate Mapping
- Spring Configuration File
- Codes That Use Your DAO