You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by ib...@incubator.apache.org on 2005/01/06 17:33:03 UTC

[Apache iBATIS Wiki] New: How do I use a Custom Type Handler with complex property (Type Safe Enumeration)

   Date: 2005-01-06T08:33:03
   Editor: NathanMaves
   Wiki: Apache iBATIS Wiki
   Page: How do I use a Custom Type Handler with complex property (Type Safe Enumeration)
   URL: http://wiki.apache.org/ibatis/How do I use a Custom Type Handler with complex property (Type Safe Enumeration)

   no comment

New Page:

##language:en
Here is an example of how to set up a custom type handler with a complex property.  This example is for a Type Safe Enumeration.

In the example below there is a class Report that represents a report that a company might produce.  This class has a complex property "frequency" that is represented by a Type Safe Enumeration.  

Here is the report table

{{{
REPORT {
	id	        varchar2(5),
	name	        varchar2(25),
	description	varchar2(1000),
	frequency	number(1)
}
}}}
As you see the frequency is stored as a number, but in the class Report is is a Frequency 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 Frequency?  Second, how can iBatis and custom type handlers help?

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

{{{
/*
 * Frequency.java
 *
 * Created on December 27, 2004, 11:00 AM
 */

package reporting.viewer.domain;

/**
 *
 * @author nmaves
 */
public class Frequency {
    
    /**
     * Holds value of property value.
     */
    private int value;
    
    /** Creates a new instance of Frequency */
    private Frequency(int value, String name) {
        this.value = value;
        this.name = name;
    }
    
    /**
     * Getter for property value.
     * @return Value of property value.
     */
    public int getValue() {
        
        return this.value;
    }
    
    private static final int FC_DAILY = 1;
    private static final int FC_WEEKLY = 2;
    private static final int FC_MONTHLY = 3;
    private static final int FC_QUARTERLY = 4;
    
    private static final String FN_DAILY = "Daily";
    private static final String FN_WEEKLY = "Weekly";
    private static final String FN_MONTHLY = "Monthly";
    private static final String FN_QUARTERLY = "Quarterly";
    
    public static final Frequency DAILY = new Frequency(FC_DAILY, FN_DAILY);
    public static final Frequency WEEKLY = new Frequency(FC_WEEKLY, FN_WEEKLY);
    public static final Frequency MONTHLY = new Frequency(FC_MONTHLY, FN_MONTHLY);
    public static final Frequency QUARTERLY = new Frequency(FC_QUARTERLY, FN_QUARTERLY);

    /**
     * Holds value of property name.
     */
    private String name;

    /**
     * Holds value of property format.
     */
    private String format;
    
    public static Frequency get(int value) {
        switch (value) {
            case FC_DAILY:      return DAILY;
            case FC_WEEKLY:	return WEEKLY;
            case FC_MONTHLY:	return MONTHLY;
            case FC_QUARTERLY:	return QUARTERLY;
            default:		return null;
        }
    }
    
    public String toString() {
        return this.name;
    }

    /**
     * Getter for property name.
     * @return Value of property name.
     */
    public String getName() {

        return this.name;
    }

}

}}}

As you see the {{{ get(int value) }}} 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 FrequencyTypeHandler.java

{{{
package reporting.viewer.dao.ibatis;

import java.sql.*;
import com.ibatis.sqlmap.client.extensions.*;
import reporting.viewer.domain.Frequency;

public class FrequencyTypeHandler implements TypeHandlerCallback {
    
    public Object getResult(ResultGetter getter) throws SQLException {
        if (getter.wasNull())
            return null;
        return Frequency.get(getter.getInt());
    }
    
    public void setParameter(ParameterSetter setter, Object parameter) throws SQLException {
        if (parameter == null) {
            setter.setNull(Types.INTEGER);
        } else {
            Frequency frequency = (Frequency) parameter;
            setter.setInt(frequency.getValue());
        }
    }
    
    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="reporting.viewer.domain.Frequency" callback="reporting.viewer.dao.ibatis.FrequencyTypeHandler"/> }}}

Make sure that you add it before the transaction manager section.

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="Report" id="ReportResult">
        <result column="id" property="id" />
        <result column="name" property="name" />
        <result column="description" property="description" />
        <result column="frequency" property="frequency"/>
</resultMap>

<select id="getReportById" parameterClass="string" resultMap="ReportResult">
        SELECT 
            *
        FROM 
            REPORT
        WHERE 
            id = #value#
</select>

<insert id="insertReport" parameterClass="Report">
        INSERT INTO 
            REPORT (
                id, 
                name, 
                frequency,
                description
                )
            values (
                #id#, 
                #name#, 
                #frequency#,
                #description#
            )
</insert>

}}}

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

Hope this helps,

Nathan Maves
Nathan.Maves@sun.com