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

Hibernate自定义类型

2013年02月24日 ⁄ 综合 ⁄ 共 3500字 ⁄ 字号 评论关闭

  Hibernate 提供了客户化映射类型接口,允许用户以编程的方式创建自定义的映射类型,以便把持久化类的任意类型的属性映射到数据库中.例1的PhoneUserType实现了net.sf.hibernate.UserType接口,它能够把Customer类的Integer类型的phone属性映射到CUSTOMER表的VARCHAR类型的PHONE字段.

例1:

package mypack;

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

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

/**
 * @author lfm
 *
 */
public class PhoneUserType implements UserType {
 
 private static final int[] SQL_TYPES = {Types.VARCHAR};
 
 public int[] sqlTypes() {
  // TODO 自动生成方法存根
  return SQL_TYPES;
 }
 
 public Class returnedClass() {
  // TODO 自动生成方法存根
  return Integer.class;
 }
 
 public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
  // TODO 自动生成方法存根
  if(resultSet.wasNull())
   return null;
  String phone = resultSet.getString(names[0]);
  return new Integer(phone);
 }
 
 public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {
  // TODO 自动生成方法存根
  if(value== null)
   arg0.setNull(index, Types.VARCHAR);
  else {
   String phone = ((Integer)value).toString();
   statement.setString(index, phone);
  }
 }
 
 public Object deepCopy(Object value) throws HibernateException {
  // TODO 自动生成方法存根
  return value;
 }
 
 public boolean equals(Object x, Object y) throws HibernateException {
  // TODO 自动生成方法存根
  if(x== y)
   return true;
  if(x== null || y== null)
   return false;
  return x.equals(y);
 }
 
 public boolean isMutable() {
  // TODO 自动生成方法存根
  return false;
 }
}

PhoneUserType实现了net.sf.hibernate.UserType接口中的所有方法,下面解释这些方法的作用.

(1)设置CUSTOMERS表的PHONE字段SQL类型,它是VARCHAR类型:

private static final int[] SQL_TYPES = {Types.VARCHAR};

public int[] sqlTypes() {return SQL_TYPES;}

(2)设置Customer类的phone属性的Java类型,它是Integer类型:

public CLass returnedClass() {return Integer.class;}

(3)Hibernate调用isMutable()方法来了解Integer类是否是可变类.本例的Integer类是不可变类,因此返回false.Hibernate处理不可变属性类型的属性时,会采取一些性能优化措施.

public boolean isMutable() {return false;}

(4)Hibernate调用deepCopy(Object value)方法来生成phone属性的快照.deepCopy()方法的value参数代表Integer类型的phone属性.由于Integer类是不可变类,因此本方法直接返回参数:

public Object deepCopy(Object value) {

  return value;

}

对于可变类,必须返回参数的拷贝值.后面会说.

(5)Hibernate调用equals(Object x, Object y)方法类比较Customer类的phone属性的当前值是否和它的快照相同.该方法的一个参数代表phone属性的当前值,一个参数代表由deepCopy()方法生成的phone属性的快照:

public boolean equals(Object x, Object y) {

  if(x== y)

    return true;

  if(x== null || y== null)

    return false;

  return x.equals(y);

}

(6)当Hibernate从数据库加载Customer对象时,调用nullSafeGet()方法类取得phone属性值.参数resultSet为JDBC查询结果集,参数names为存放了表字段名的数组,此处为{"PHONE"},参数owner代表phone属性的宿主,此处为Customer对象.

public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException,SQLException {

  if(resultSet.wasNull()) return null;

  String phone = resultSet.getString(names[0]);

  return new Integer(phone);

}

在nullSafeGet方法中,先从ResultSet从读取PHONE字段的值,然后把它转换为Integer对象,最后将它作为phone属性值返回.

(7)当Hibernate把Customer对象持久化到数据库中时,调用nullSafeSet()方法来把phone属性添加到INSERT SQL语句中.statement参数包含了预定义的INSERT SQL语句,参数value代表phone属性,参数index代表把phone属性插入到INSERT SQL语句中的位置:

public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {

  if(value == null) {

    statement.setNull(index, Types.VARCHAR);

  }else{

    String phone = ((Integer)value).toString();

    statement.setString(index, phone);

  }

}

在nullSafeSet()方法中,参数value代表phone属性.因此,先把Integer类型的value转换为String类型,然后把它添加到JDBC Statement中.

定义了PhoneUserType类后,在Customer.hbm.xml中按如下方式映射Customer类的phone属性:

<property name="name" type="mypack.PhoneUserType">

  <column name="phone" length="8"/>

</property>

PhoneUserType不仅仅可以用来映射phone属性,事实上,它能够把持久化类的任何一个Integer类型的属性映射到数据库中VARCHAR类型的字段.

抱歉!评论已关闭.