Hibernate自定义类型取代Hibernate主件

本文介绍如何设计一个不可变类Address,并实现一个自定义类型AddressUserType,用于映射数据库字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本讲把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配置方式,因此具有较好的可维护性.自定义类型采用的是编程方式,能够完成更加复杂灵活的映射.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值