现在的位置: 首页 > 综合 > 正文

UserType取代枚举类型

2014年02月21日 ⁄ 综合 ⁄ 共 3723字 ⁄ 字号 评论关闭

  枚举类型是一种常见的Java设计模式.在枚举类型的Java类中,定义了这个类本身是一些静态实例.例1定义了一个Gender类,它包含两个静态常量类型的Gender实例:Gender.FEMALE和Gender.MALE.Gender类有两个属性:sex和description.sex属性代表性别的缩写,可选值'F'和'M';description属性代表性别的完整名字,可选值为"Female"和"MALE".

例1:

package mypack;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * @author lfm
 *
 */
public class Gender implements Serializable {

 private final Character sex;
 
 private final transient String description;

 public String getDescription() {
  return description;
 }

 public Character getSex() {
  return sex;
 }
 
 private static final Map instanceBySex = new HashMap();
 
 public Gender(Character sex, String description) {
  this.sex = sex;
  this.description = description;
  instanceBySex.put(sex, description);
 }
 
 public static final Gender FEMALE = new Gender(new Character('F'), "Female");
 
 public static final Gender MALE = new Gender(new Character('M'), "Male");
 
 public static Collection getAllValues() {
  return Collections.unmodifiableCollection(instanceBySex.values());
 }
 
 public static Gender getInstanceBySex(Character sex) {
  Gender result = (Gender)instanceBySex.get(sex);
  if(result == null)
   throw new NoSuchElementException(sex.toString());
  return result;
 }
 
 public String toString() {
  return description;
 }
 
 private Object readResolve() {
  return getInstanceBySex(sex);
 }
}

当业务类型中有一些固定的常量数据,就可以用枚举类型的类来实现.枚举类型的优点在于节省内存空间.以Gender类为例,当程序运行后,在内存中只可能有两个Gender实例:Gender.FEMALE和Gender.MALE.Gender类封装了构造方法,不允许外部程序构造Gender实例.

假定在Customer类中有一个Gender类型的gender属性,在CUSTOMERS表中有一个CHAR(1)类型的GENDER字段,可选值为'F'和'M'.可以创建一个GenderUserType类,它负责把持久化类的Gender类型的属性映射到数据库中CHAR(1)类型的字段.例2是GenderUserType类的源程序.

例2:

package mypack;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.NoSuchElementException;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.UserType;

/**
 * @author lfm
 *
 */
public class GenderUserType implements UserType {

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#sqlTypes()
  */
 public int[] sqlTypes() {
  // TODO 自动生成方法存根
  return new int[]{Types.CHAR};
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#returnedClass()
  */
 public Class returnedClass() {
  // TODO 自动生成方法存根
  return Gender.class;
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
  */
 public boolean equals(Object x, Object y) throws HibernateException {
  // TODO 自动生成方法存根
  //由于内存中只可能有两个静态常量Gender实例,因此可以直接按内存地址比较
  return x == y;
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
  */
 public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
   throws HibernateException, SQLException {
  // TODO 自动生成方法存根
  Character sex = (Character)Hibernate.CHARACTER.nullSafeGet(rs, names[0]);
  if(sex == null)
  return null;
  try {
   return Gender.getInstanceBySex(sex);
  }catch (NoSuchElementException e) {
   // TODO: handle exception
   throw new HibernateException("Bad Gender value: " + sex, e);
  }
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
  */
 public void nullSafeSet(PreparedStatement st, Object value, int index)
   throws HibernateException, SQLException {
  // TODO 自动生成方法存根
  Character sex = null;
  if(value != null)
   sex = ((Gender)value).getSex();
  Hibernate.CHARACTER.nullSafeSet(st, sex, index);
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
  */
 public Object deepCopy(Object value) throws HibernateException {
  // TODO 自动生成方法存根
  return (Gender)value;
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#isMutable()
  */
 public boolean isMutable() {
  // TODO 自动生成方法存根
  return false;
 }

}

创建了GenderUserType类后,只需按如下方式映射Customer类的gender属性:

<property name="gender" type="mypack.GenderUserType">

  <column name="SEX" length="1"/>

</property>

抱歉!评论已关闭.