[ 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