Friday, September 01, 2006
Enum Type in Hibernate Mapping
參考這篇「Java 5 EnumUserType」文章
就直接用昨天Generic CRUD DAO程式來改吧!
EnumUserType.java
以這個EnumUserType class來轉接Enum Type
package util; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.usertype.EnhancedUserType; import org.hibernate.usertype.ParameterizedType; /** * @author Gavin King */ public class EnumUserType implements EnhancedUserType, ParameterizedType { private Class<Enum> enumClass; public void setParameterValues(Properties parameters) { String enumClassName = parameters.getProperty("enumClassName"); try { enumClass = (Class<Enum>) Class.forName(enumClassName); } catch (ClassNotFoundException cnfe) { throw new HibernateException("Enum class not found", cnfe); } } public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } public Object deepCopy(Object value) throws HibernateException { return value; } public Serializable disassemble(Object value) throws HibernateException { return (Enum) value; } public boolean equals(Object x, Object y) throws HibernateException { return x == y; } public int hashCode(Object x) throws HibernateException { return x.hashCode(); } public boolean isMutable() { return false; } public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { String name = rs.getString(names[0]); return rs.wasNull() ? null : Enum.valueOf(enumClass, name); } public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { if (value == null) { st.setNull(index, Types.VARCHAR); } else { st.setString(index, ((Enum) value).name()); } } public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } public Class returnedClass() { return enumClass; } public int[] sqlTypes() { return new int[] { Types.VARCHAR }; } public Object fromXMLString(String xmlValue) { return Enum.valueOf(enumClass, xmlValue); } public String objectToSQLString(Object value) { return '\'' + ((Enum) value).name() + '\''; } public String toXMLString(Object value) { return ((Enum) value).name(); } }
Person.java
加入一個Gender enum type
package genericdaotest.domain; import java.io.Serializable; public class Person implements Serializable { private Long id; private String name; private Gender gender; private Integer weight; public Person(String name, Gender gender, Integer weight) { this.name = name; this.gender = gender; 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 Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } }
Gender.java
package genericdaotest.domain; public enum Gender { MALE, FEMALE }
Person.hbm.xml
修改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="gender"> <type name="util.EnumUserType"> <param name="enumClassName"> genericdaotest.domain.Gender </param> </type> </property> <property name="weight" /> </class> </hibernate-mapping>
PersonDaoTest.java
修改test case
package genericdaotest; import genericdao.GenericDao; import genericdaotest.domain.Gender; 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; /** * Simple test of the PersonDao */ 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", Gender.MALE, 88); personDao.create(createPerson); assertNotNull(createPerson.getId()); Long id = createPerson.getId(); restartSession(); // Read Person foundPerson = (Person) personDao.read(id); assertEquals(createPerson.getGender(), foundPerson.getGender()); restartSession(); // Update Gender updateGender = Gender.FEMALE; foundPerson.setGender(updateGender); personDao.update(foundPerson); Person updatedPerson = (Person) personDao.read(id); assertEquals(updateGender, updatedPerson.getGender()); 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"); } }