Dashboard > iBATIS DataMapper > Home > Frequently Asked Questions > How do I use a Custom Type Handler with complex property or Type Safe Enumeration
How do I use a Custom Type Handler with complex property or Type Safe Enumeration
Added by Clinton Begin, last edited by Nathan Maves on Feb 27, 2006  (view change)
Labels: 
(None)


Here is an example of how to set up a custom type handler with a complex property. This example uses the enum features of Java 1.5 but could be used with a Type Safe Enumeration in anything below 1.5.

Lets start by defining the database table

SHAPE {
    name    varchar2(25),
    color   number(100)
    }

As you see the color is stored as a number, but in the class Shape is is a Color object. There are two question that I ran into. First, how do you cleanly map the number stored in the database with the instance of a Color? Second, how can iBatis and custom type handlers help?

To answer the first let me show you the code for the Shape class.

/*
    * Shape.java
    *
    * Created on September 23, 2005
    */
    package domain;
    /**
    *
    * @author nmaves
    */
    public class Shape {
    public enum Color {
    BLUE(1, "0000FF"), RED(2, "FF0000"), GREEN(3, "00FF00");
    
    private int id;
    private String rgb;
    
    private Type(int id, String name) {
    this(id, name, "no mime type");
    
    }
    
    private Type(int id, String rgb) {
    this.id = id;
    this. rgb = rgb;
    }
    
    public int getId() {
    return this.id;
    }
    
    public String getRGB() {
    return this.name;
    }
    
    public static Type getInstance(int i) {
    for(Color color : Color.values()) {
    if(color.id == i) {
    return type;
    }
    }
    
    throw new IllegalArgumentException("No such Color");
    }
    }
    
    private String name;
    private Color color;
    
    /** Creates a new instance of Frequency */
    private Shape(String name, Color color) {
    this.color = color;
    this.name = name;
    }
    
    
    public String toString() {
    return this.name;
    }
    
    
    public void setName(String name) {
    this.name = name;
    }
    public void setColor(Color color) {
    this.color = color;
    }
    
    public String getName() {
    return this.name;
    }
    public Color getColor() {
    return this.color;
    }
    
    }

As you see the getInstance(int i) method allows for the mapping of the number stored in the database to an instance of this class. I am sure there is a better way of pulling these initial value from a properties file but this is only an example.

For the second part you will need a way to allow iBatis to make the conversion. This is where the custom type handler comes into play.

Below is my ColorTypeHandler.java

package dao.ibatis;
    
    import com.ibatis.sqlmap.client.extensions.ParameterSetter;
    import com.ibatis.sqlmap.client.extensions.ResultGetter;
    import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
    import java.sql.SQLException;
    import java.sql.Types;
    import Shape.Color;
    
    
    public class ColorTypeHandler implements TypeHandlerCallback {
    public Object getResult(ResultGetter getter) throws SQLException {
    int value = getter.getInt();
    if (getter.wasNull()) {
    return null;
    }
    Color color = Color.getInstance(value);
    
    return color;
    }
    
    public void setParameter(ParameterSetter setter, Object parameter)
    throws SQLException {
    if (parameter == null) {
    setter.setNull(Types.INTEGER);
    } else {
    Color color = (Color) parameter;
    setter.setInt(color.getId());
    }
    }
    
    public Object valueOf(String s) {
    return s;
    }
    }

You are almost there! All you need left to do is tell iBatis to map instances of Frequency object to this handler.

I added the following line into my SqlMapConfig file.

<typeHandler javaType="domain.Shape$Color" callback="dao.ibatis.ColorTypeHandler"/>
Useful Information

Notice the $ in the class name. This is how Java 1.5 denotes enums. If this were a type safe enum you would just use standard notation.

That is it. No need to change any of your other sqlmap entries. Here is an example of a select and insert that use this handler.

<resultMap class="Shape" id="ShapeResult">
    <result column="name" property="name" />
    <result column="color" property="color" />
    </resultMap>
    
    <select id="getShapeByName" parameterClass="string" resultMap="ShapeResult">
    SELECT
    *
    FROM
    SHAPE
    WHERE
    name = #value#
    </select>
    
    <insert id="insertReport" parameterClass="Report">
    INSERT INTO
    SHAPE (
    name,
    color
    )
    values (
    #name#,
    #color#,
    )
    </insert>

Notice that there is nothing special that need to be done for the color columns.


Site running on a free Atlassian Confluence Open Source Project License granted to OSS. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.5 Build:#811 Jul 25, 2007) - Bug/feature request - Contact Administrators