Here's one possible solution that is based on Gavin's EnumUserType
(http://www.hibernate.org/272.html). EnumUserType allows using any Enum
without subclassing. I changed his version to use the ordinals rather
than the String representations of enums. Now I verified the persisting
works (at least in my simple environment), but haven't tried to map a
row back to an object. In any event, here's my mapping doc:
<class name="com.product.client.Client">
<id name="id" column="CLIENT_ID">
<generator class="native"/>
</id>
<property name="name" />
<property name="clientType">
<type name="com.product.hibernate.EnumUserType">
<param
name="enumClassName">com.product.client.ClientType</param>
</type>
</property>
</class>
Here's the modified EnumUserType:
public class EnumUserType implements EnhancedUserType,
ParameterizedType {
private Class<Enum> enumClass;
@SuppressWarnings("unchecked")
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enumClassName");
try {
enumClass = (Class<Enum>) Class.forName(enumClassName);
} catch (ClassNotFoundException cnfe) {
throw new HibernateException("Enum class not found", cnfe);
}
}
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
public Object deepCopy(Object value) throws HibernateException {
return value;
}
public Serializable disassemble(Object value)
throws HibernateException {
return (Enum) value;
}
public boolean equals(Object x, Object y)
throws HibernateException {
return x == y;
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public boolean isMutable() {
return false;
}
@SuppressWarnings("unchecked")
public Object nullSafeGet(ResultSet rs, String[] names,
Object owner) throws HibernateException, SQLException {
int ordinal = rs.getInt(names[0]);
//Don't know if we are guaranteed to get the ordinals
//in the right order with toArray() below.
return rs.wasNull() ? null
: EnumSet.allOf(enumClass).toArray()[ordinal];
}
public void nullSafeSet(PreparedStatement st, Object value,
int index) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.INTEGER);
} else {
st.setInt(index, ((Enum) value).ordinal());
}
}
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
public Class returnedClass() {
return enumClass;
}
public int[] sqlTypes() {
return new int[] { Types.INTEGER };
}
@SuppressWarnings("unchecked")
public Object fromXMLString(String xmlValue) {
return Enum.valueOf(enumClass, xmlValue);
}
public String objectToSQLString(Object value) {
return new StringBuffer(((Enum) value).ordinal()).toString();
}
public String toXMLString(Object value) {
return objectToSQLString(value);
}
} |