[ 
http://issues.apache.org/jira/browse/IBATIS-332?page=comments#action_12454806 ] 
            
John Didion commented on IBATIS-332:
------------------------------------

+1

This is really important for mapping Java 5 enum types.

> 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


Reply via email to