-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Typesafe enum and usertype proper use for a codetable?
PostPosted: Thu Jul 28, 2005 5:06 pm 
Newbie

Joined: Thu Jul 28, 2005 4:03 pm
Posts: 1
First of all this is definitely a new user question.
What we are trying to do is map a code table (Errors) that has values that will never change in our database.
It has only a few fields like code, description, severity.
We wanted to use typesafe enums in our code to ensure type safety.
The examples i see of use the usertype classes for typesafe enums in hibernate 2 all only show the
simple example where we just have a single value in the database like an integer or something.
Like in here (http://www.hibernate.org/203.html)

What we want is our entire error code object to be used and loaded so we can get the description or severity out.
Also so when an object that has an Error in the Error in the object can be compared to the typesafe value.

Hibernate version:2

Mapping documents:
Code:
<class
    name="bell.horizon.persistence.horizondb.ErrorCode"
    table="ERROR"

    mutable="false"
>
    <cache usage="read-only"/>

    <id
        name="errorId"
        type="java.lang.Long"
        column="ERROR_ID"
    >
        <generator class="sequence">
            <param name="sequence">ERROR_SEQ</param>
        </generator>

    </id>

    <property
        name="errorCode"
        type="java.lang.String"
        column="ERROR_CODE"
        not-null="true"
        length="20"
    />
    <property
        name="errorSeverity"
        type="java.lang.String"
        column="ERROR_SEVERITY"
        length="20"
    />
    <property
        name="description"
        type="java.lang.String"
        column="DESCRIPTION"
        length="512"
    />

</class>



Code between sessionFactory.openSession() and session.close():

Code:
public class ErrorCode implements Serializable {

    /* Section allows for the usage of extended/enumerated UserType ErrorUType */
    /* Keeps track of all instances by name, for efficient lookup. */
    private static final Map instancesById = new HashMap();
    private static final Map instancesByCode = new HashMap();

    public static final ErrorCode SAG_INVALID       = new ErrorCode("SAG_INVALID",       new Long(1));
    public static final ErrorCode DUPLICATE_ADD     = new ErrorCode("DUPLICATE_ADD",     new Long(2));
    public static final ErrorCode UPDATE_NO_ADD     = new ErrorCode("UPDATE_NO_ADD",     new Long(3));
    public static final ErrorCode UPDATE_INVALID    = new ErrorCode("UPDATE_INVALID",    new Long(4));
    public static final ErrorCode BLIF_PERSISTENCE  = new ErrorCode("BLIF_PERSISTENCE",  new Long(5));
    public static final ErrorCode DD_CHANGE         = new ErrorCode("DD_CHANGE",         new Long(6));
    public static final ErrorCode INFLIGHT_UPDATE   = new ErrorCode("INFLIGHT_UPDATE",   new Long(7));
    public static final ErrorCode VERSION_INVALID   = new ErrorCode("VERSION_INVALID",   new Long(8));
    public static final ErrorCode DELETE_NO_ADD     = new ErrorCode("DELETE_NO_ADD",     new Long(9));
    public static final ErrorCode DELETE_INVALID    = new ErrorCode("DELETE_INVALID",    new Long(10));
    public static final ErrorCode INFLIGHT_DELETE   = new ErrorCode("INFLIGHT_DELETE",   new Long(11));

    private Long errorId;
    private String errorCode;
    private String errorSeverity;
    private String description;
    public ErrorCode() {
    }

    /* TaskType constructor */
    public ErrorCode(String errorCode, Long errorId) {
        this.errorCode = errorCode;
        this.errorId = errorId;
        // Record this instance in the collection that tracks the enumeration
        instancesByCode.put(errorCode, this);
        instancesById.put(errorId, this);
    }


    public Long getErrorId() {
        return this.errorId;
    }

    public void setErrorId(Long errorId) {
        this.errorId = errorId;
    }

    public String getErrorCode() {
        return this.errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorSeverity() {
        return this.errorSeverity;
    }

    public void setErrorSeverity(String errorSeverity) {
        this.errorSeverity = errorSeverity;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    /**
     * Obtain the collection of all legal enumeration values.
     *
     * @return all instances of this typesafe enumeration.
     */
    public static Collection getAllValues() {
        return Collections.unmodifiableCollection(instancesByCode.values());
    }

    /**
     * Look up an instance by errorCode.
     *
     * @param errorCode the external name of an instance.
     * @return the corresponding instance.
     * @throws NoSuchElementException if there is no such instance.
     */
    public static ErrorCode getInstanceByType(String errorCode) {
        ErrorCode result = (ErrorCode) instancesByCode.get(errorCode);
        if (result == null) {
            throw new NoSuchElementException(errorCode);
        }
        return result;
    }

    /**
     * Look up an instance by description.
     *
     * @param id the external name of an instance.
     * @return the corresponding instance.
     * @throws NoSuchElementException if there is no such instance.
     */
    public static ErrorCode getInstanceById(Long id) {
        ErrorCode result = (ErrorCode) instancesById.get(id);
        if (result == null) {
            throw new NoSuchElementException(id.toString());
        }
        return result;
    }

    /**
     * Insure that deserialization preserves the signleton property.
     */
    private Object readResolve() {
        return getInstanceByType(errorCode);
    }

    public String toString() {
        return "Error{" +
                "errorId=" + errorId +
                ", errorCode='" + errorCode + "'" +
                ", errorSeverity='" + errorSeverity + "'" +
                ", description='" + description + "'" +
                "}";
    }
}


public class ErrorUType implements UserType {

   public boolean isMutable() {
       return false;
    }

    public Object deepCopy(Object value) {
        return (ErrorCode)value;
    }

   public boolean equals(Object x, Object y) {
      // We can compare instances, since Error are immutable singletons
      return (x == y);
   }

  public Class returnedClass() {
       return ErrorCode.class;
   }

   public int[] sqlTypes() {
       // Allocate a new array each time to protect against callers changing
       // its contents.
       int[] typeList = {
          Types.NUMERIC
       };
       return typeList;
    }

   public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
       throws HibernateException, SQLException
   {
        // Start by looking up the value name
        Long id = (Long) Hibernate.LONG.nullSafeGet(rs, names[0]);
        if (id == null || id == new Long(0)) {
            return null;
        }
     // Then find the corresponding enumeration value
     try {
        // return Error.getInstanceByType(name);
         return bell.horizon.persistence.horizondb.ErrorCode.getInstanceById(id);
     }

     catch (java.util.NoSuchElementException e) {
        throw new HibernateException("Bad Error type value: " + id, e);
     }
   }

  public void nullSafeSet(PreparedStatement st, Object value, int index)
      throws HibernateException, SQLException
  {
      Long id = null;
      if (value != null)
          id = ((ErrorCode)value).getErrorId();
      Hibernate.LONG.nullSafeSet(st, id, index);

  }
}



Sample calling code....

taskStatus.setErrorCode(ErrorCode.DUPLICATE_ADD);
horizonService.updateTaskStatus(taskStatus);

another sample (code that we wished we had).....

if (taskStatus.getErrorCode().equals(ErrorCode.DUPLICATE_ADD)) {

// send message
}


what we really have for the above........
// ignore the ugly fact that our class is called ErrorCode and it has a field called error code as
// this was a bad choice to get away from java.lang.Error conficting with our Error (rename refactored
// Error to ErrorCode without looking at the internals)

if (taskStatus.getErrorCode().getErrorCode.equals(ErrorCode.DUPLICATE_ADD.getErrorCode()) {
// send message
}

The first sample works for us in that the taskStatus table gets the foreign key inserted that points to the proper error.


What i don't understand/like is that in order for the equality check to work in the second sample i would need
to change my static constructor to contain all the fields that are in the database. This doesn't seem
right to me to duplicate all of the information.

Maybe we shouldn't be using a typesafe enum/usertype but instead should just access the object through the DAO and reload it
from the database using one of the available caching schemes?

Can anyone point me to a more appropriate example? (We do use this similar thing in 3 different places so far)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.