<component name="homeAddress" class="Address"> <property name="street" type="string" column="HOME_STREET"/> <property name="city" type="string" column="HOME_CITY"/> <property name="zipcode" type="string" column="HOME_ZIPCODE"/> </component>
这个值类型映射很简单,用户自定义的新Java类型的所有属性都被映射到内建的SQL数据类型的单独的列。然而,也可以选择利用一个定制的映射类型把它当作一个简单的属性来映射:
<property name="homeAddress" type="auction.persistence.CustomAddressType"> <column name="HOME_STREET"/> <column name="HOME_CITY"/> <column name="HOME_ZIPCODE"/> </property>当然,在这个例子中,使用定制的映射类型替换组件映射的好处是令人置疑的。只要在加载和保存这个对象时不需要特殊的转化,现在必须编写的CustomAddressType就是额外的工作。然而,你可能已经看到定制的映射类型提供了一个额外的缓冲区——当在长期运行中需要额外的转化时,可能派得上用场的东西。
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class MonetaryAmount implements Serializable {
	private static final long serialVersionUID = -3446177576184667883L;
	private final BigDecimal amount;
	private final Currency currency;
	public MonetaryAmount(BigDecimal amount, Currency currency) {
		super();
		this.currency = currency;
		this.amount = amount;
	}
	public BigDecimal getAmount() {
		return amount;
	}
	public Currency getCurrency() {
		return currency;
	}
	
	public boolean equals(Object obj) {
		if (null == obj) {
			return false;
		}
		if (obj == this) {
			return true;
		}
		if (obj.getClass() != this.getClass()) {
			return false;
		}
		MonetaryAmount ma = (MonetaryAmount) obj;
		return new EqualsBuilder().append(this.getAmount(), ma.getAmount())
				.isEquals();
	}
	public int hashCode() {
		final int PRIME = 31;
		return new HashCodeBuilder(this.getAmount().intValue(), PRIME)
				.toHashCode();
	}
}注意,必须实现equals()和hashCode()来完成类。package cn.jbit.hibernate.entity;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Currency;
import org.hibernate.HibernateException;
import org.hibernate.type.BigDecimalType;
import org.hibernate.usertype.UserType;
public class MonetaryAmountType implements UserType {
	
	//告诉Hibernate要使用什么SQL列类型生成DDL模式
	public int[] sqlTypes() {
		return new int[] { BigDecimalType.INSTANCE.sqlType() };
	}
	
	//映射Java值类型
	@SuppressWarnings("unchecked")
	public Class returnedClass() {
		return MonetaryAmount.class;
	}
	
	//这个类型是否可变
	public boolean isMutable() {
		return false;
	}
	
	//创建值的快照
	public Object deepCopy(Object value) throws HibernateException {
		return value;
	}
	//以序列化的形保存信息的数据的高速缓存
	public Serializable disassemble(Object value) throws HibernateException {
		return (Serializable) value;
	}
	
	//高速缓存的数据转变为MonetaryAmount的一个实例
	public Object assemble(Serializable cached, Object owner)
			throws HibernateException {
		return cached;
	}
	//处理脱管对象状态的合并
	public Object replace(Object original, Object target, Object owner)
			throws HibernateException {
		return original;
	}
	
	public boolean equals(Object x, Object y) throws HibernateException {
		if (x == y)
			return true;
		if (null == x || null == y)
			return false;
		return x.equals(y);
	}
	public int hashCode(Object x) throws HibernateException {
		return x.hashCode();
	}
	//从JDBC的ResultSet获取属性值
	public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
			throws HibernateException, SQLException {
		BigDecimal valueInUSD = resultSet.getBigDecimal(names[0]);
		// Deferred check after first read
		if (resultSet.wasNull())
			return null;
		Currency userCurrency = User.getPreferences().getCurrency();
		MonetaryAmount amount = new MonetaryAmount(valueInUSD, "USD");
		return amount.convertTo(userCurrency);
	}
	
	//把属性值写到JDBC的PreparedStatement
	public void nullSafeSet(PreparedStatement pstmt, Object value, int index)
			throws HibernateException, SQLException {
		if (null == value) {
			pstmt.setNull(index, BigDecimalType.INSTANCE.sqlType());
		} else {
			MonetaryAmount anyCurrency = (MonetaryAmount) value;
			MonetaryAmount amountInUSD = MonetaryAmount.convert(anyCurrency, Currency.getInstance("USD"));
			pstmt.setBigDecimal(index, anyCurrency.getAmount());
		}
	}
}现在映射Item的initialPrice属性如下:<property name = "initialPrice"
    column = "INITIAL_PRICE"
    type = "persistence.MonetaryAmountUserType"/>注意你把定制的用户类型放进了persistence包;它是应用程序的持久层的一部分,而不是领域模型或者业务层的一部分。@org.hibernate.annotations.Type(
    type = "persistence.MonetaryAmountUserType"
)
@Column(name = "INITIAL_PRICE")
private MonetaryAmount initialPrice;这是UserType可以执行的一种最简单的转化。更加复杂的事情也有可能。定制的映射类型可以执行验证;它可以把数据读取和写入到一个LDAP目录;它甚至可以从不同的数据库获取持久化对象。Hibernate实战_笔记32(考虑定制的映射类型、创建UserType),布布扣,bubuko.com
Hibernate实战_笔记32(考虑定制的映射类型、创建UserType)
原文:http://blog.csdn.net/com185272358/article/details/22430815