Version 2

    User type mappings

     

    Since 3.2.2.

     

    Sometimes we would like to have some custom Java type as a CMP field but store it in the database column as, for example, some kind of numerical or string value.

     

    An example could be a constant enumeration colors. We have a CMP field of type ColorEnum which can have of the three possible values ColorEnum.RED, ColorEnum.GREEN or ColorEnum.BLUE.

     

    /*
     * JBoss, the OpenSource J2EE webOS
     *
     * Distributable under LGPL license.
     * See terms of license at gnu.org.
     */
    package org.jboss.test.cmp2.enum.ejb;
    
    
    /**
     * Enum implementations for colors.
     *
     * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
     */
    public abstract class ColorEnum
    {
       private static int nextOrdinal = 0;
    
       // Constants
    
       private static final ColorEnum VALUES[] =  new ColorEnum[3];
    
       public static final ColorEnum RED = new Red("RED");
       public static final ColorEnum GREEN = new Green("GREEN");
       public static final ColorEnum BLUE = new Blue("BLUE");
    
       // Attributes
    
       private final Integer ordinal;
       private final transient String name;
    
       // Constructor
    
       private ColorEnum(String name)
       {
          this.name = name;
          this.ordinal = new Integer(nextOrdinal++);
          VALUES[ordinal.intValue()] = this;
       }
    
       // Public
    
       public Integer getOrdinal()
       {
          return ordinal;
       }
    
       public String toString()
       {
          return name;
       }
    
       public ColorEnum valueOf(int ordinal)
       {
          return VALUES[ordinal];
       }
    
       // Inner
    
       private static final class Red extends ColorEnum
       {
          public Red(String name)
          {
             super(name);
          }
       }
    
       private static final class Green extends ColorEnum
       {
          public Green(String name)
          {
             super(name);
          }
       }
    
       private static final class Blue extends ColorEnum
       {
          public Blue(String name)
          {
             super(name);
          }
       }
    }
    

     

    But we want to store the field of ColorEnum type as interger in the database not a serialized Java object. We can do it by implementing the following interface:

     

    /*
     * JBoss, the OpenSource J2EE webOS
     *
     * Distributable under LGPL license.
     * See terms of license at gnu.org.
     */
    package org.jboss.ejb.plugins.cmp.jdbc;
    
    
    /**
     * Generally, implementations of this interface map instances of one Java type
     * into instances of another Java type.
     * Mappers can be used in cases when instances of "enum" types are used as CMP
     * field values. In this case, a mapper represents a mediator and translates
     * instances of "enum" to some id when the field is stored
     * and back from id to "enum" instance when the data is loaded.
     *
     * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
     */
    public interface Mapper
    {
       /**
        * This method is called when CMP field is stored.
        * @param fieldValue - CMP field value
        * @return column value.
        */
       Object toColumnValue(Object fieldValue);
    
       /**
        * This method is called when CMP field is loaded.
        * @param columnValue - loaded column value.
        * @return CMP field value.
        */
       Object toFieldValue(Object columnValue);
    }
    

     

    An implementation for ColorEnum could be

     

    /*
     * JBoss, the OpenSource J2EE webOS
     *
     * Distributable under LGPL license.
     * See terms of license at gnu.org.
     */
    package org.jboss.test.cmp2.enum.ejb;
    
    import org.jboss.ejb.plugins.cmp.jdbc.Mapper;
    
    
    /**
     * org.jboss.ejb.plugins.cmp.jdbc.Mapper implementation.
     * Maps ColorEnum to Integer.
     *
     * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
     */
    public class ColorMapper
       implements Mapper
    {
       public Object toColumnValue(Object fieldValue)
       {
          return ((ColorEnum)fieldValue).getOrdinal();
       }
    
       public Object toFieldValue(Object columnValue)
       {
          int ordinal = ((Integer)columnValue).intValue();
          return ColorEnum.RED.valueOf(ordinal);
       }
    }
    

     

     

    Now, in jbosscmp-jdbc.xml we specify that we want to use our wrapper

     

       <user-type-mappings>
          <user-type-mapping>
             <java-type>org.jboss.test.cmp2.enum.ejb.ColorEnum</java-type>
             <mapped-type>java.lang.Integer</mapped-type>
             <mapper>org.jboss.test.cmp2.enum.ejb.ColorMapper</mapper>
          </user-type-mapping>
       </user-type-mappings>
    

     

    Now all the fields of type ColorEnum will use the ColorMapper.

     

    The DTD for user-type-mapping in jbosscmp-jdbc_3_2.dtd is

     

    <!--
      Defines a mapping of a user type to a column providing a mapper class.
      Mapper is like a mediator: when storing, it takes an instance of the user
      type and translates it to a column value; when loading, it takes a column
      value and translates it to an instance of the user type.
    -->
    <!ELEMENT user-type-mapping (java-type, mapped-type, mapper, check-dirty-after-get?, state-factory?)>