Utiliser des enum de Java5 avec Hibernate
Lorsque la gestion du typage d’une base de donnees relationnelle est confiee a Java et Hibernate, il est souvent frustrant de perdre la securite induite par les enum de Java 5. Voici comment reconcilier Hibernate et les enum.
Tout d’abord, definissez une classe EnumUserType
. Elle sera utilisee par tous les enums de votre projet:
// laissez Eclipse gerer les imports... public class EnumUserType<E extends Enum<E>> implements UserType { private Class<E> clazz = null; protected EnumUserType(Class<E> c) {this.clazz = c;} private static final int[] SQL_TYPES = {Types.VARCHAR}; public int[] sqlTypes() {return SQL_TYPES;} public Class returnedClass() {return clazz;} public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { String name = resultSet.getString(names[0]); E result = null; if (!resultSet.wasNull()) { result = Enum.valueOf(clazz, name); } return result; } public int hashCode(Object x) throws HibernateException { return x.hashCode(); } 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 void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException { if (null == value) { preparedStatement.setNull(index, Types.VARCHAR); }else { preparedStatement.setString(index, ((Enum) value).name()); } } public Object deepCopy(Object value) throws HibernateException {return value;} public boolean isMutable() {return false;} public Object assemble(Serializable cached, Object owner) throws HibernateException {return cached;} public Serializable disassemble(Object value) throws HibernateException {return (Serializable) value;} public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } }
Ensuite, definissez votre enum de maniere classique, disons:
public enum Toto{ // le minimum: TATA, TETE, TUTU; // je conseille de surcharger ces deux methodes: public String getName() { return name(); } public String toString() { return name(); } }
Puis, realisez le lien entre votre enumeration et l’EnumUserType
public class TotoEnumUserType extends EnumUserType<Toto> { public TotoEnumUserType() { super(Totoclass); } }
Supposons qu’un objet de type Tata a un champ de type Toto, le Pojo aura une apparence tout ce qu’il y a de plus classique
public class Tata{ private Toto toto; public Toto getToto(){...} public void setToto(Toto _toto){...} }
Voila pour le cote Java. Le mapping Hibernate proprement dit sera obtenu grace a la description suivante dans le fichier de mapping:
<property name="myField" type="TotoEnumUserType"/>
Le champ Toto sera sauvegarde en base sous la forme de chaines de caracteres comme TATA
, correspondant au name()
du champ de l’enumeration.