ibatis-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jay Blanton (JIRA)" <ibatis-...@incubator.apache.org>
Subject [jira] Created: (IBATIS-332) Exposing javaType (resultMap/parameterMap) attribute in TypeHandler methods for Superclass/Subclass handlers.
Date Thu, 10 Aug 2006 18:00:16 GMT
Exposing javaType (resultMap/parameterMap) attribute in TypeHandler methods for Superclass/Subclass
handlers.
-------------------------------------------------------------------------------------------------------------

                 Key: IBATIS-332
                 URL: http://issues.apache.org/jira/browse/IBATIS-332
             Project: iBatis for Java
          Issue Type: Improvement
          Components: SQL Maps
    Affects Versions: 2.1.7
         Environment: WebLogic 8.1.5, Oracle 9i, Solaris
            Reporter: Jay Blanton


This improvement is inregards to TypeHandler and its usage with Superclasses/Subclasses. 
Currently we have an Abstract object (TypeSafeEnumeration) that users will extend to create
their own specific implementations of our TypeSafeEnumeration.  When they want to map this
data type in iBatis, they have to create a specific handler for each implementation of the
TypeSafeEnumeration.  What we would like to accomplish is to create a single handler for the
superclass.  But in order to do this...methods like the getResult in the TypeHandler interface
would need to know how to take a VARCHAR from the database and create the specific implementation
of that superclass.  This information is not available to getResult (but not needed in the
setParameter), so therefore a handler must be created specific to each implementation.  I
would like to register a superclass with a global typeHandler in my sqlMapConfig that can
handle the conversion for each specific implementation of that superclass, by utilizing the
javaType (for example).

So a superclass could be registered as the the global javaType with a superclass based TypeHandler.
 Then each resultMap/parameterMap could defined the specific implementation in the javaType
and the TypeHandler could use that resultMap/parameterMap javaType to instantiate the specific
version of that superclass.

I have included below the TO that is getting mapped, and the Superclass (Abstract) that needs
the TypeHandler, and two specific implementations of that TypeHandler:

TO:
public class ContactTO {
    
    private GenderType gender;
    private ContactMethodType contactMethod;
    public ContactMethodType getContactMethod() {
        return this.contactMethod;
    }
    public void setContactMethod(ContactMethodType contactMethod) {
        this.contactMethod = contactMethod;
    }
    public GenderType getGender() {
        return this.gender;
    }
    public void setGender(GenderType gender) {
        this.gender = gender;
    }
    
}

Superclass (Enum)
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Iterator;

/**
* Base class for type-safe Enumeration to provide a consistent interface and
* common methods, and to make Castor-ation easier.
*/
public abstract class AbstractTypeSafeEnumeration implements Serializable {
    private static Hashtable _types = new Hashtable();

    private String _value;
    private String _displayValue;

    public static final AbstractTypeSafeEnumeration getTypeByValue(String value, Class clazz
) {

        Hashtable classType = (Hashtable)_types.get(clazz.getName());
        AbstractTypeSafeEnumeration out = (AbstractTypeSafeEnumeration)classType.get(value);
        return out;
    }

    public static final AbstractTypeSafeEnumeration getTypeByDisplayValue(String displayValue,
Class clazz)
    {
        Hashtable classType = (Hashtable)_types.get(clazz.getName());
        Iterator values = classType.values().iterator();
        AbstractTypeSafeEnumeration value = null;
        while (values.hasNext() && value == null)
        {
            AbstractTypeSafeEnumeration tempValue = (AbstractTypeSafeEnumeration) values.next();
            if (value.getDisplayValue().equals(displayValue)) {
                value = tempValue;
            }
        }
        return value;
    }

    protected AbstractTypeSafeEnumeration( String value, String displayValue ) {
        this._value = value;
        this._displayValue = displayValue;
        synchronized( _types ) {
            String className = this.getClass().getName();
            Hashtable classType = ( Hashtable )_types.get( className );
            if( classType == null ) {
                classType = new Hashtable();
                _types.put( className, classType );
            }
            classType.put( value, this );
       }
    }

    public final String getValue() {
        return this._value;
    }

    public final String getDisplayValue() {
        return this._displayValue;
    }

}

Implementations of Enum (located in ContactTO)
import com.foo.to.AbstractTypeSafeEnumeration;

/**
 * This class is a type-safe Enumeration of ContactMethodTypes.
 *
 * @author Jay Blanton
 */
public class ContactMethodType extends AbstractTypeSafeEnumeration {
    public static final ContactMethodType PHONE = new ContactMethodType("P", "Phone");
    public static final ContactMethodType MAIL = new ContactMethodType("M", "Mail");
    public static final ContactMethodType UNKNOWN = new ContactMethodType("U", "Unknown");


    /**
     * Creates a new ContactMethodType object.
     *
     * @param intValue param
     * @param displayString param
     */
    private ContactMethodType(String value, String displayString) {
        super(value, displayString);
    }
}

import com.foo.to.AbstractTypeSafeEnumeration

public class GenderType extends AbstractTypeSafeEnumeration {
    public static final GenderType FEMALE = new GenderType("F", "Female");
    public static final GenderType MALE = new GenderType("M", "Male");
    public static final GenderType UNKNOWN = new GenderType("U", "Unknown");

    /**
     * Creates a new GenderType object.
     *
     * @param intValue param
     * @param displayString param
     */
    private GenderType(String value, String displayString) {
        super(value, displayString);
    }
}

This is what we would like to see:

Global Type Handler:
<typeHandler javaType="com.foo.to.AbstractTypeSafeEnumeration" callback="com.foo.dao.datahandler.AbstractTypeSafeEnumerationTypeHandler"/>

Specific Result Map for ContactTO:
<resultMap id="loadContact" class="com.foo.to.ContactTO">
    <result property="gender" column="GENDER" jdbcType="VARCHAR" javaType="com.foo.to.GenderType"/>
    <result property="contactMethod" column="METHOD" jdbcType="VARCHAR" javaType="com.foo.to.ContactMethodType"/>
   
</resultMap>


Sample of a pseudo NewTypeHandler that has access to javaType:

public class AbstractTypeSafeEnumerationTypeHandler implements NewTypeHandler {

    /**
     * This method overrides the default setParameter method in TypeHandler.
     * 
     * @param ps param
     * @param i param
     * @param parameter param
     * @param jdbcType param
     *
     * @throws SQLException can be thrown
     */
    public void setParameter(PreparedStatement ps, int i, Object parameter, String jdbcType)
      throws SQLException {    
        if(parameter == null) {
            JdbcType type = (JdbcType)JdbcType.getTypeByDisplayValue(jdbcType, JdbcType.class);
            int sqlType = Integer.parseInt(type.getValue());
            ps.setNull(i, sqlType);
        }
        else {
            AbstractTypeSafeEnumeration enum = (AbstractTypeSafeEnumeration)parameter;
            ps.setString(i, enum.getValue());
        }
    }

    private AbstractTypeSafeEnumeration getEnum(String value, String javaType) {
        Class clazz = null;
        try {
            clazz = Class.forName(javaType);
        }
        catch (ClassNotFoundException e) {
            throw new RuntimeException("Invalid javaType - This class does not exist: ->
" + javaType, e); 
        }
        return AbstractTypeSafeEnumeration.getTypeByValue(value, clazz);
    }
    
    /**
     * This method overrides the default getResult method in TypeHandler.
     * 
     * @param rs param
     * @param columnName param
     *
     * @return returned
     *
     * @throws SQLException can be thrown
     */
    public Object getResult(ResultSet rs, String columnName, String javaType)
      throws SQLException {
        String result = rs.getString(columnName);
        return this.getEnum(result, javaType);
    }

    /**
     * This method overrides the default getResult method in TypeHandler.
     * 
     * @param rs param
     * @param columnIndex param
     *
     * @return returned
     *
     * @throws SQLException can be thrown
     */
    public Object getResult(ResultSet rs, int columnIndex, String javaType)
      throws SQLException {
        String result = rs.getString(columnIndex);
        return this.getEnum(result, javaType);
    }


    /**
     * This method overrides the default getResult method in TypeHandler.
     * 
     * @param cs param
     * @param columnIndex param
     *
     * @return returned
     *
     * @throws SQLException can be thrown
     */
    public Object getResult(CallableStatement cs, int columnIndex, String javaType)
      throws SQLException {
            String result = cs.getString(columnIndex);
            return this.getEnum(result, javaType);
    }


    /**
     * This method overrides the default equals method in TypeHandler.
     * 
     * @param object param
     * @param dbVal param
     *
     * @return returned
     */
    public boolean equals(Object object, String dbVal) {
        return StringHelper.equals(((AbstractTypeSafeEnumeration)object).getValue(), dbVal);
    }


    /**
     * This method overrides the default valueOf method in TypeHandler.
     * 
     * @param dbVal param
     *
     * @return returned
     */
    public Object valueOf(String dbVal) {
        return dbVal;
    }
}
 



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

Mime
View raw message