//这个类型是否可变
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包;它是应用程序的持久层的一部分,而不是领域模型或者业务层的一部分。
为了在注解中使用定制类型,必须添加一个Hibernate扩展:
@org.hibernate.annotations.Type(
type = "persistence.MonetaryAmountUserType"
)
@Column(name = "INITIAL_PRICE")
private MonetaryAmount initialPrice;
这是UserType可以执行的一种最简单的转化。更加复杂的事情也有可能。定制的映射类型可以执行验证;它可以把数据读取和写入到一个LDAP目录;它甚至可以从不同的数据库获取持久化对象。
简单的UserType实现的缺点在于,Hibernate不知道有关MonetaryAmount内部单独属性的任何信息。它所知的只是定制类型类和列名称。Hibernate查询引擎不知道如何查询amount或者特定的currency.
如果需要Hibernate查询的全部功能,就编写CompositeUserType.这个(稍微有点复杂的)接口把MonetaryAmount的属性公开给Hibernate查询。现在再次用这个更灵活的定制接口把它映射到两个列,实际上生成了组件映射的等价物。