I finally got a custom type handler working properly (see code below) but I
still contend there is a bug with output parameter mapping in IBatis for
null database values. In MappedStatement.RetrieveOutputParameters:175
without a custom type handler it uses the UnknownTypeHandler to set the
dataBaseValue object which then blows up in line 178 when it goes to call
SetOutputParameter. I don't really have the time right now to see exactly
why the Set cannot handle the DBNull type as I saw that alot of reflection
and dynamic method instantiation is used for setting values and it would
take me a while to figure out how it works.
class DbNullTypeHandler : ITypeHandlerCallback
{
public void SetParameter(IParameterSetter setter, object parameter)
{
if (parameter != null)
{
if (parameter.Equals(DateTime.MinValue))
{
setter.Value = System.DBNull.Value;
}
else
{
setter.Value = parameter;
}
}
}
public object GetResult(IResultGetter getter)
{
if (getter.Value.Equals(System.DBNull.Value))
{
return NullValue;
}
else
{
return getter.Value;
}
}
public object ValueOf(string nullValue)
{
return nullValue;
}
public object NullValue
{
get {return null; }
}
}
> steve dunning
> Wed, 27 Aug 2008 13:20:13 -0700
>
> I am using a parameter class to encapsulate the input and output
> parameters
> for an Oracle stored procedure that I am calling. When the stored proc
> returns data for all of the Output parameters all is well, however, when
> null values are returned in any of the parameters, well, that is when
> things
> fall apart. It seems that the problem lies somewhere when converting the
> System.DBNull value that is coming back from the database. A
> System.InvalidCastException is thrown for any parameter that contains a
> null.
>
> I found the following JIRA entry
> https://issues.apache.org/jira/browse/IBATISNET-247 that seemed to
> describe
> the problem that I am encountering. I thought, no problem I will just
> create a custom type handler to manually convert to the right type.
> After
> reading many mail group threads and much experimentation I cannot seem
> to
> get that working either. Using the type handler then causes valid
> return
> parameters to fail with cast exceptions.
>
> *Any guidance or suggestions would be greatly appreciated!*
>
> *Here is a snippet from my sqlMap config:*
>
> <alias>
> <typeAlias alias="DbNullHandler"
> type="Domain.Name.Persistence.Handlers.DbNullTypeHandler,Persistence"/>
> </alias>
>
> <parameterMaps>
> <parameterMap id="tsrHeader-param"
> class="Domain.Name.Persistence.ParameterClasses.TsrHeaderParam,Persisten
> ce"
> >
> <parameter property="p_req_id" direction="Input" />
> <parameter property="date_time_group" direction="Output"
> column="date_time_group" size="100"
> />
> <!--typeHandler="DbNullHandler" type="DateTime"
> dbType="Date"/>-->
> <parameter property="message_dest" direction="Output"
> column="message_dest" size="1000" />
> <parameter property="message_origin" direction="Output"
> column="message_origin" size="1000" />
> <parameter property="message_cc" direction="Output"
> column="message_cc" size="1000" />
> <parameter property="return_code" direction="Output"
> column="return_code"
> precision="5" scale="0" size="5" type="Decimal"/>
> </parameterMap>
> </parameterMaps>
>
> <statements>
> <procedure id="getTsrHeader" parameterMap="tsrHeader-param">
> DUNNING_element_tsrHeader
> </procedure>
> </statements>
>
> *This is the Custom Type Handler snippet:*
>
> class DbNullTypeHandler : ITypeHandlerCallback
> {
> #region ITypeHandlerCallback Members
>
> public void SetParameter(IParameterSetter setter, object
> parameter)
> {
> if (parameter.Equals(DateTime.MinValue))
> {
> setter.Value = System.DBNull.Value;
> }
> else
> {
> setter.Value = parameter;
> }
> }
>
> public object GetResult(IResultGetter getter)
> {
> if (getter.Value.Equals(System.DBNull.Value))
> {
> return DateTime.MinValue;
> }
> else
> {
> return getter.Value;
> }
> }
>
> public object ValueOf(string nullValue)
> {
> return nullValue;
> }
>
> public object NullValue
> {
> get {return System.DBNull.Value; }
> }
>
> *And this is the parameter class:*
>
> public class TsrHeaderParam
> {
> private string _p_req_id;
> public string p_req_id
> {
> get { return _p_req_id; }
> set { _p_req_id = value; }
> }
>
> private DateTime _date_time_group;
> public DateTime date_time_group
> {
> get { return _date_time_group; }
> set { _date_time_group = value; }
> }
>
> private string _message_origin;
> public string message_origin
> {
> get { return _message_origin; }
> set { _message_origin = value; }
> }
>
> private string _message_dest;
> public string message_dest
> {
> get { return _message_dest; }
> set { _message_dest = value; }
> }
>
> private string _message_cc;
> public string message_cc
> {
> get { return _message_cc; }
> set { _message_cc = value; }
> }
>
> private Decimal _return_code;
> public Decimal return_code
> {
> get { return _return_code; }
> set { _return_code = value; }
> }
> }
> Classification: UNCLASSIFIED
> Caveats: NONE
>
>