EnumCodeUserType.java

  1. package org.itracker.persistence.dao;

  2. import org.apache.log4j.Logger;
  3. import org.hibernate.HibernateException;
  4. import org.itracker.model.IntCodeEnum;

  5. import java.sql.PreparedStatement;
  6. import java.sql.ResultSet;
  7. import java.sql.SQLException;
  8. import java.sql.Types;
  9. import java.util.Properties;

  10. /**
  11.  * Custom Hibernate UserType to persist a Java 5 enum constant
  12.  * that implement {@link org.itracker.model.IntCodeEnum } as an INTEGER
  13.  * using its integer code.
  14.  * <p/>
  15.  * <p>This should be preferred to using the enum.ordinal() or enum.name(). </p>
  16.  *
  17.  * @author johnny
  18.  */
  19. public class EnumCodeUserType extends AbstractEnumUserType {

  20.     private static final int[] SQL_TYPES = {Types.SMALLINT};
  21.     private static final Logger log = Logger.getLogger(EnumCodeUserType.class);
  22.     /**
  23.      * Enum members, in the order they where declared.
  24.      */
  25.     @SuppressWarnings("unchecked")
  26.     private IntCodeEnum[] enumValues;

  27.     /**
  28.      * Default constructor, required by Hibernate.
  29.      */
  30.     public EnumCodeUserType() {
  31.     }

  32.     public void setParameterValues(Properties parameters) {
  33.         super.setParameterValues(parameters);
  34.         this.enumValues = (IntCodeEnum[]) this.enumClass.getEnumConstants();
  35.     }

  36.     public Object nullSafeGet(ResultSet rs, String[] names,
  37.                               Object owner) throws HibernateException, SQLException {
  38.         final int code = rs.getInt(names[0]);

  39.         /* It is safe to assume there's always at least 1 enum constant
  40.         * because the compiler ensures that enums are never empty.
  41.         *
  42.         * Note : fromCode cannot be static in IntEnumCode !
  43.         */
  44.         try {
  45.             return rs.wasNull() ? null : this.enumValues[0].fromCode(code);
  46.         } catch (Exception e) {
  47.             log.info("nullSafeGet: failed to get default code enum, trying DEFAULT-code " + IntCodeEnum.DEFAULT_CODE, e);
  48.             return this.enumValues[0].fromCode(IntCodeEnum.DEFAULT_CODE);
  49.         }
  50.     }

  51.     public void nullSafeSet(PreparedStatement stmt, Object value,
  52.                             int index) throws HibernateException, SQLException {
  53.         if (value == null) {
  54.             stmt.setNull(index, Types.INTEGER);
  55.         } else {
  56.             stmt.setInt(index, ((IntCodeEnum<?>) value).getCode());
  57.         }
  58.     }

  59.     public int[] sqlTypes() {
  60.         return SQL_TYPES;
  61.     }

  62.     public String objectToSQLString(Object value) {
  63.         return Integer.toString(((IntCodeEnum<?>) value).getCode());
  64.     }

  65.     public String toXMLString(Object value) {
  66.         return objectToSQLString(value);
  67.     }

  68.     public Object fromXMLString(String xmlValue) {
  69.         final int code;

  70.         try {
  71.             code = Integer.parseInt(xmlValue);
  72.         } catch (NumberFormatException ex) {
  73.             throw new HibernateException(ex);
  74.         }

  75.         /* It is safe to assume there's always at least 1 enum constant
  76.         * because the compiler ensures that enums are never empty.
  77.         *
  78.         * Note : fromCode cannot be static in IntEnumCode !
  79.         */
  80.         return this.enumValues[0].fromCode(code);
  81.     }

  82. }