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

Hibernate自定义类型取代Hibernate主件

2014年02月18日 ⁄ 综合 ⁄ 共 4150字 ⁄ 字号 评论关闭

本讲把Address设计为不可变类.所谓不可变类,是指当创建了这种类的实例后,就不允许修改它的属性.在Java API中,所有的基本类型的包装类,如Integer和Long类,都是不可变类,java.lang.String也是不可变类.在创建用户自己的不可变类时,可以考虑采用以下的设计模式.

a.把属性定义为private final类型.

b.不对外公开用于修改属性的setXXX()方法.

c.只对外公开用于读取属性的getXXX()方法.

d.允许在构造函数中设置所有属性.

e.覆盖Object类的equals()和hashCode()方法

例1:

package mypack;

/**
 * @author lfm
 *
 */
import java.io.Serializable;

public class Address implements Serializable {

 private final String province;

 private final String city;

 private final String street;

 private final String zipcode;

 public Address(String province, String city, String street, String zipcode) {
  this.province = province;
  this.city = city;
  this.street = street;
  this.zipcode = zipcode;
 }

 public String getProvince() {
  return this.province;
 }

 public String getCity() {
  return this.city;
 }

 public String getStreet() {
  return this.street;
 }

 public String getZipcode() {
  return this.zipcode;
 }

 public boolean equals(Object o) {
  if (this == null || !(o instanceof Address))
   return false;
  final Address address = (Address) o;
  if (!province.equals(address.province))
   return false;
  if (!city.equals(address.city))
   return false;
  if (!street.equals(address.street))
   return false;
  if (!zipcode.equals(address.zipcode))
   return false;
  return true;
 }

 public int hashCode() {
  int result;
  result = (province == null ? 0 : province.hashCode());
  result = 29 * result + (city == null ? 0 : city.hashCode());
  result = 29 * result + (street == null ? 0 : street.hashCode());
  result = 29 * result + (zipcode == null ? 0 : zipcode.hashCode());
  return result;
 }
}

由于Address类是不可变类,因此创建了Address类的实例后,就无法修改它的属性.如果要修改属性,必须使它引用一个新的Address实例.

例2是AddressUserType的源程序,它实现了UserType接口:

例2:

package mypack;

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

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

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

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

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

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
  */
 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);
 }

 /* (非 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 自动生成方法存根
  if(rs.wasNull())
   return null;
  String province = rs.getString(names[0]);
  String city = rs.getString(names[1]);
  String street = rs.getString(names[2]);
  String zipcode = rs.getString(names[3]);
  return new Address(province, city, street, zipcode);
 }

 /* (非 Javadoc)
  * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
  */
 public void nullSafeSet(PreparedStatement statement, Object value, int index)
   throws HibernateException, SQLException {
  // TODO 自动生成方法存根
  if(value == null) {
   statement.setNull(index, Types.VARCHAR);
   statement.setNull(index + 1, Types.VARCHAR);
   statement.setNull(index + 2, Types.VARCHAR);
   statement.setNull(index + 3, Types.VARCHAR);
  }else{
   Address obj = (Address)value;
   statement.setString(index, obj.getProvince());
   statement.setString(index + 1, obj.getCity());
   statement.setString(index + 2, obj.getStreet());
   statement.setString(index + 3, obj.getZipcode());
  }
 }

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

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

}

创建了以上的AddressUserType后,就可以按以下方式映射属性了:

<property name="address" type="mypack.AddressUserType">

  <column name="HOME_STREET" length="15"/>

  <column name="HOME_CITY" length="15"/>

  <column name="HOME_PROVINCE" length="15"/>

  <column name="HOME_ZIPCODE" length="6"/>

</property>

Hibernate组件和用户自定义类型都是值类型,在某些情况下能够完成同样的功能,到底选择何种方式,取决于用户自己的喜好.总的来说,Hibernate组件采用的是XML配置方式,因此具有较好的可维护性.自定义类型采用的是编程方式,能够完成更加复杂灵活的映射.

抱歉!评论已关闭.