I (like half the developers on earth, it seems) have a UserType for mapping org.apache.commons.lang.enums.Enum. It is a parameterized user type, which I typically use like this:
Code:
public class MonkeyColor extends Enum {
...
}
public class Monkey {
private MonkeyColor color;
...
}
<property name="color">
<type name="org.mpr.common.persistence.hibernate.EnumType">
<param name="enumClass">org.mpr.monkeyapp.model.MonkeyColor</param>
</type>
</property>
Yes, yes, I know -- I'd rather be using Java's enum facility, and Hibernate will eventually support than in all sorts of fancy ways. But right now we're stuck on 1.4.2 on our production servers. :(
Anyway, suppose I want to have a multicolored monkey. My class would then look like:
Code:
public class Monkey {
private Set<MonkeyColor> color;
...
}
And I'd really want to map it like this:
Code:
<set name="availableColors" table="monkeyColors">
<key column="monkeyId"/>
<element>
<type name="org.mpr.common.persistence.hibernate.EnumType">
<param name="enumClass">org.mpr.monkeyapp.model.MonkeyColor</param>
</type>
</element>
</set>
But according to the mapping file DTD, I can't do that, because "type" is only allowable as an attribute of "element", not as a nested subelement:
Code:
<!ELEMENT element (column|formula)*>
<!ATTLIST element column CDATA #IMPLIED>
<!ATTLIST element node CDATA #IMPLIED>
<!ATTLIST element formula CDATA #IMPLIED>
<!ATTLIST element type CDATA #REQUIRED>
<!ATTLIST element length CDATA #IMPLIED>
<!ATTLIST element precision CDATA #IMPLIED>
<!ATTLIST element scale CDATA #IMPLIED>
<!ATTLIST element not-null (true|false) "false">
<!ATTLIST element unique (true|false) "false">
Is this just a missing feature in the DTD? Or does Hibernate not support a collection of parameterized user types at all?
I dug around on the web a bit, but couldn't find any info about this question.
Hibernate version: 3.0.5
My EnumType class, FWIW:
Code:
package org.mpr.common.persistence.hibernate;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
import org.apache.commons.lang.enums.Enum;
import org.apache.commons.lang.enums.EnumUtils;
import org.hibernate.HibernateException;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
public class EnumType implements UserType, ParameterizedType {
public static final int[] SQL_TYPES = new int[]{ Types.VARCHAR };
private Class enumClass;
public int[] sqlTypes() {
return SQL_TYPES;
}
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enumClass");
try {
enumClass = Class.forName(enumClassName);
} catch (ClassNotFoundException e) {
throw new HibernateException("Class " + enumClassName + " not found ", e);
}
if(!Enum.class.isAssignableFrom(enumClass))
throw new HibernateException(enumClass + " does not extend " + Enum.class);
}
public Class returnedClass() {
return enumClass;
}
public boolean equals(Object x, Object y) throws HibernateException {
return (x == y);
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
String name = rs.getString(names[0]);
return rs.wasNull() ? null : EnumUtils.getEnum(enumClass, name);
}
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.INTEGER);
} else {
st.setString(index, ((Enum)value).getName());
}
}
public Object deepCopy(Object value) throws HibernateException {
return value;
}
public boolean isMutable() {
return false;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}