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?)>
Comments