-->
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.  [ 2 posts ] 
Author Message
 Post subject: Complex enums mapped as a class not property with manyto-one
PostPosted: Wed Mar 12, 2008 2:07 pm 
Newbie

Joined: Wed Mar 12, 2008 9:05 am
Posts: 1
Hello everybody,

We have been racking our brains about this one for a bit, and wanted to see if anyone had any experience in doing something similar. The basic idea that we are trying to accomplish is to map complex enums (an example of which is below) as the receiving class of a many-to-one relationship in another object. The idea is to enforce the application to always have the same data inside its enumeration as that located within the DB.

For example, an example Enum, we shall call CardStatusEnum

Code:
public enum CardStatusEnum implements PKIEnumeration {
   RED(1, "Non Assegnata"),
   BLUE(2, "Assegnata"),
   GREEN(3, "Attiva");
   
   private long id;
   private String description;
   private CardStatusEnum (long id, String description){
      this.id = id;
      this.description = description;
   }
   public  Object getEnumValue(Object[] enumValues){
      Integer id = (Integer) enumValues[0];
      String description = (String) enumValues[1];
      if(id == 1){
         if(!description.equals(RED.description))
            throw new RuntimeException();
         return RED;
      }
      else if(id==2){
         if(!description.equals(BLUE.description))
            throw new RuntimeException();
         return BLUE;
      }
      else if(id==3){
         if(description.equals(GREEN.description))
            throw new RuntimeException();
            return GREEN;
         
      }
       throw new RuntimeException();
      
   }
   public  int[] getEnumSQLTypes(){
      return new int[]{Types.INTEGER, Types.VARCHAR};
   }
}


We want to have other object be able to directly have a field CardStatusEnum that will be persisted/read to the DB as a foreign key column in that objects mapped table.

After searching through a couple posts that used enums, the common method we found to be used was that of using a specified userType or enumType directly on the property field of the class which held the enum. This allows one to save the enum inside the DB either as a string or id but without doing any kind of verification of what is saved inside the DB versus what is saved inside the enumeration class. We had also taken this approach and had written a class which implented UserType, and had all our enumerations implement a certain interface, PKIEnumeration ...

Code:
public class PKIEnumerationUserType<E extends Enum<E> & PKIEnumeration> implements UserType {
   private Class<E> clazz = null;

   protected PKIEnumerationUserType(Class<E> c) {
      this.clazz = c;
      EnumSet<E> enums = EnumSet.allOf(c);
      Iterator<E> it = enums.iterator();
      enumInstance = it.next();
      SQL_TYPES = enumInstance.getEnumSQLTypes();
   }

   private final int[] SQL_TYPES;
   private final E enumInstance;

   public int[] sqlTypes() {
      return SQL_TYPES;
   }

   public Class<E> returnedClass() {
      return clazz;
   }

   public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
         throws HibernateException, SQLException {
      boolean hitID = false;
      ArrayList<Object> list = new ArrayList<Object>();
      for(String currParam : names){
         if(!hitID){
            Long id = resultSet.getLong(currParam);
            if(id == null)
               return null;
            list.add(id);
         }
         list.add(resultSet.getObject(currParam));
      }
      return enumInstance.getEnumValue(list.toArray());
   }

   public void nullSafeSet(PreparedStatement preparedStatement, Object value,
         int index) throws HibernateException, SQLException {
      throw new UnsupportedOperationException();
   }

   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;
   }

   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);
   }
}



This would work if the enumeration values (in our case an integer and string) are stored in the same table as the object which has the enumeration as a field. However, we would like to keep the look-up table behavior in our DB. So, the question is how can we specify something similar to the 'type' variable as in:

Code:
<property name='cardStatus'>
    <type name="PKIEnumerationUserType">
      <param name="enumClassName">CardStatusEnum </param>
    </type>
  </property>


where instead of using a property tag we want to use a many-to-one tag, does something along the lines of this exist or even possible ...

Code:
<many-to-one name="cardStatus"
                      type="PKIEnumerationUserType"
            class="CardStatusEnum"
            column="DETAILID" lazy="false" not-null="true">
</many-to-one>


Of course if the constructor of a java enum wasnt private then I guess this wouldnt be a question. Thanks for any help, we would greatly appreciate it. Maybe we have to write a special entity persister class? Thanks again for any help from the Hibernate gurus.

Michele


Top
 Profile  
 
 Post subject: Enum FK and persisted to DB.
PostPosted: Mon May 12, 2008 11:25 am 
Newbie

Joined: Fri Apr 14, 2006 1:04 am
Posts: 6
Have you found a solution to this problem?


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

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.