You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user-java@ibatis.apache.org by Vadim Grinshpun <va...@ll.mit.edu> on 2008/01/18 17:24:06 UTC

"can't infer the SQL type" of a bean property whose type is a generic parameter.

Hi all,

I just ran into an interesting problem, and I'm curious whether I'm 
doing something wrong, or if it's a known limitation or bug in iBATIS 
(or its interaction with the JDBC driver?). I'm using iBATIS 2.3.0 with 
a PostgreSQL's jdbc driver 8.2-504.

Let's say I have the following classes:

// wrapper that attaches an attribute to things; a poor-man's mix-in class
class Wrapper<T>{
    String wrapperAttribute;
    T value;
    String getAttribute() { return wrapperAttribute;}
    T getValue() { return value; };
     // remaining bean accessors are defined but not shown
     // ...
}

// a class that uses the  wrapper:
class FooBean{
   Wrapper<String> wrappedString;
   Wrapper<Date> wrappedDate;
   Wrapper<SomeEnum> wrappedEnum; // Enum and its TypeHandlerCallback 
are defined elsewhere, not shown
   // the obvious get/set accessors are defined below, not shown
   // ...
}
// end code

FooBean is then passed as a parameter to an insert statement, which 
looks, roughly, along the lines of:

 <insert ... >
      INSERT INTO mytable ( string_field, date_field, enum_field )
      VALUES( #wrappedString.value#,
                      #wrappedDate.value#,
                      #wrappedEnum.value# )
 </insert>
 
When trying to run the code, the #wrappedString.value# part of the 
statement works just fine, but for the #wrappedDate.value# I  get an error:
    "PSQLException: Can't infer the SQL type to use for an instance of 
java.util.Date. Use setObject() with an explicitly Types value to 
specify the type to use."

Seeing this, I tried adding the jdbc type to the parameter map, as shown:
                      #wrappedDate.value:TIMESTAMP#
This produced the same exact error.

Then I tried adding a wrapper method,"Date getWrappedDateValue" which 
simply calls getWrappedDate().getValue(), and thus returns a Date 
object, but then I got the same error for the wrappedEnum...

Can anyone explain this? Is there a way to get this to work properly? I 
first thought that this has to do with Java's generic not preserving 
enough information for this to work, but as the error message clearly 
shows, the type info is retrievable...
Thanks for any insight!

-Vadim


Re: "can't infer the SQL type" of a bean property whose type is a generic parameter.

Posted by Jeff Butler <je...@gmail.com>.
I don't think we would call this a bug - more like a "known limitation".
The current version of iBATIS is compiled for JDK 1.4 so there's nothing we
can do to introspect generic classes.  The next version of iBATIS will
require JDK 5.0 or higher so we'll be able to do better there.

Jeff Butler

On Jan 23, 2008 2:04 PM, Vadim Grinshpun <va...@ll.mit.edu> wrote:

> Specifying javaType does seem to work around the problem, and might be
> better than introducing wrapper methods (as I originally did)
> However, I'd really like to find out is whether this is a bug in iBATIS
> (in which case I can file a bug report), or if this is expected behaviour
> and/or known limitation  (in which case it would be good to document it
> somewhere, I guess).
> I hope someone knowledgeable about iBATIS internals can voice their
> opinion on that...
>
> Thanks,
> -Vadim
>
>
>
> paulomourajr wrote:
>
> Hi, Grinshpun,
>
> I faced this same problem a couple of hours ago. In my case, I have a
> generic class like this (names were changed for the sake of
> confidentiality):
>
> public class GenericModel<PK extends Serializable> {
>
>      protected PK id;
>
>     public PK getId(){
>        return id;
>     }
>
>     public void setId(PK value){
>          this.id = value;
>     }
> }
>
> and one class like this:
>
> public UF extends GenericModel<Long> {
>
>     private String name;
>
>     //getters and setters
> }
>
> The original result map and update statement generated using abator were
> like this:
>
>   <resultMap class="UF" id="UFResult">
>     <result column="COD_UF" jdbcType="BIGINT" property="id"/>
>     <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
>   </resultMap>
>
>   <update id="updateByPrimaryKey" parameterClass="UF">
>     update uf
>     set NAM_UF = #name:VARCHAR#
>     where COD_UF = #id:BIGINT#
>   </update>
>
> When I tried to use them, I got the same problem you reported. One solution
> I found was to specify the java type in each statement using this property.
> Changed result map and update statement are here:
>
>   <resultMap class="UF" id="UFResult">
>     <result column="COD_UF" jdbcType="BIGINT" property="id"
> javaType="long"/>
>     <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
>   </resultMap>
>
>   <update id="updateByPrimaryKey" parameterClass="UF">
>     update uf
>     set NAM_UF = #name:VARCHAR#
>     where COD_UF = #id,javaType=long,jdbcType
> =BIGINT#
>   </update>
>
> After this, everything went fine. But I found this solution a little
> cumbersome, since it is not a special type which requires a special type
> handler. Anybody has another alternative to this?
>
> Regards.
>
>
> Vadim Grinshpun wrote:
>
>
> Hi all,
>
> I just ran into an interesting problem, and I'm curious whether I'm
> doing something wrong, or if it's a known limitation or bug in iBATIS
> (or its interaction with the JDBC driver?). I'm using iBATIS 2.3.0 with
> a PostgreSQL's jdbc driver 8.2-504.
>
> Let's say I have the following classes:
>
> // wrapper that attaches an attribute to things; a poor-man's mix-in class
> class Wrapper<T>{
>     String wrapperAttribute;
>     T value;
>     String getAttribute() { return wrapperAttribute;}
>     T getValue() { return value; };
>      // remaining bean accessors are defined but not shown
>      // ...
> }
>
> // a class that uses the  wrapper:
> class FooBean{
>    Wrapper<String> wrappedString;
>    Wrapper<Date> wrappedDate;
>    Wrapper<SomeEnum> wrappedEnum; // Enum and its TypeHandlerCallback
> are defined elsewhere, not shown
>    // the obvious get/set accessors are defined below, not shown
>    // ...
> }
> // end code
>
> FooBean is then passed as a parameter to an insert statement, which
> looks, roughly, along the lines of:
>
>  <insert ... >
>       INSERT INTO mytable ( string_field, date_field, enum_field )
>       VALUES( #wrappedString.value#,
>                       #wrappedDate.value#,
>                       #wrappedEnum.value# )
>  </insert>
>
> When trying to run the code, the #wrappedString.value# part of the
> statement works just fine, but for the #wrappedDate.value# I  get an
> error:
>     "PSQLException: Can't infer the SQL type to use for an instance of java.util.Date. Use setObject() with an explicitly Types value to
> specify the type to use."
>
> Seeing this, I tried adding the jdbc type to the parameter map, as shown:
>                       #wrappedDate.value:TIMESTAMP#
> This produced the same exact error.
>
> Then I tried adding a wrapper method,"Date getWrappedDateValue" which
> simply calls getWrappedDate().getValue(), and thus returns a Date
> object, but then I got the same error for the wrappedEnum...
>
> Can anyone explain this? Is there a way to get this to work properly? I
> first thought that this has to do with Java's generic not preserving
> enough information for this to work, but as the error message clearly
> shows, the type info is retrievable...
> Thanks for any insight!
>
> -Vadim
>
>
>
>
>
>
>

Re: "can't infer the SQL type" of a bean property whose type is a generic parameter.

Posted by Vadim Grinshpun <va...@ll.mit.edu>.
Specifying javaType does seem to work around the problem, and might be 
better than introducing wrapper methods (as I originally did)
However, I'd really like to find out is whether this is a bug in iBATIS 
(in which case I can file a bug report), or if this is expected 
behaviour and/or known limitation  (in which case it would be good to 
document it somewhere, I guess).
I hope someone knowledgeable about iBATIS internals can voice their 
opinion on that...

Thanks,
-Vadim


paulomourajr wrote:
> Hi, Grinshpun,
>
> I faced this same problem a couple of hours ago. In my case, I have a
> generic class like this (names were changed for the sake of
> confidentiality):
>
> public class GenericModel<PK extends Serializable> {
>
>      protected PK id;
>
>     public PK getId(){
>        return id;
>     }
>
>     public void setId(PK value){
>          this.id = value;
>     }
> }
>
> and one class like this:
>
> public UF extends GenericModel<Long> {
>
>     private String name;
>
>     //getters and setters
> }
>
> The original result map and update statement generated using abator were
> like this:
>
>   <resultMap class="UF" id="UFResult">
>     <result column="COD_UF" jdbcType="BIGINT" property="id"/>
>     <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
>   </resultMap>
>
>   <update id="updateByPrimaryKey" parameterClass="UF">
>     update uf
>     set NAM_UF = #name:VARCHAR#
>     where COD_UF = #id:BIGINT#
>   </update>
>
> When I tried to use them, I got the same problem you reported. One solution
> I found was to specify the java type in each statement using this property.
> Changed result map and update statement are here:
>
>   <resultMap class="UF" id="UFResult">
>     <result column="COD_UF" jdbcType="BIGINT" property="id"
> javaType="long"/>
>     <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
>   </resultMap>
>
>   <update id="updateByPrimaryKey" parameterClass="UF">
>     update uf
>     set NAM_UF = #name:VARCHAR#
>     where COD_UF = #id,javaType=long,jdbcType
> =BIGINT#
>   </update>
>
> After this, everything went fine. But I found this solution a little
> cumbersome, since it is not a special type which requires a special type
> handler. Anybody has another alternative to this?
>
> Regards.
>
>
> Vadim Grinshpun wrote:
>   
>> Hi all,
>>
>> I just ran into an interesting problem, and I'm curious whether I'm 
>> doing something wrong, or if it's a known limitation or bug in iBATIS 
>> (or its interaction with the JDBC driver?). I'm using iBATIS 2.3.0 with 
>> a PostgreSQL's jdbc driver 8.2-504.
>>
>> Let's say I have the following classes:
>>
>> // wrapper that attaches an attribute to things; a poor-man's mix-in class
>> class Wrapper<T>{
>>     String wrapperAttribute;
>>     T value;
>>     String getAttribute() { return wrapperAttribute;}
>>     T getValue() { return value; };
>>      // remaining bean accessors are defined but not shown
>>      // ...
>> }
>>
>> // a class that uses the  wrapper:
>> class FooBean{
>>    Wrapper<String> wrappedString;
>>    Wrapper<Date> wrappedDate;
>>    Wrapper<SomeEnum> wrappedEnum; // Enum and its TypeHandlerCallback 
>> are defined elsewhere, not shown
>>    // the obvious get/set accessors are defined below, not shown
>>    // ...
>> }
>> // end code
>>
>> FooBean is then passed as a parameter to an insert statement, which 
>> looks, roughly, along the lines of:
>>
>>  <insert ... >
>>       INSERT INTO mytable ( string_field, date_field, enum_field )
>>       VALUES( #wrappedString.value#,
>>                       #wrappedDate.value#,
>>                       #wrappedEnum.value# )
>>  </insert>
>>  
>> When trying to run the code, the #wrappedString.value# part of the 
>> statement works just fine, but for the #wrappedDate.value# I  get an
>> error:
>>     "PSQLException: Can't infer the SQL type to use for an instance of 
>> java.util.Date. Use setObject() with an explicitly Types value to 
>> specify the type to use."
>>
>> Seeing this, I tried adding the jdbc type to the parameter map, as shown:
>>                       #wrappedDate.value:TIMESTAMP#
>> This produced the same exact error.
>>
>> Then I tried adding a wrapper method,"Date getWrappedDateValue" which 
>> simply calls getWrappedDate().getValue(), and thus returns a Date 
>> object, but then I got the same error for the wrappedEnum...
>>
>> Can anyone explain this? Is there a way to get this to work properly? I 
>> first thought that this has to do with Java's generic not preserving 
>> enough information for this to work, but as the error message clearly 
>> shows, the type info is retrievable...
>> Thanks for any insight!
>>
>> -Vadim
>>
>>
>>
>>     
>
>   


Re: "can't infer the SQL type" of a bean property whose type is a generic parameter.

Posted by paulomourajr <pa...@paulomourajr.net>.
Hi, Grinshpun,

I faced this same problem a couple of hours ago. In my case, I have a
generic class like this (names were changed for the sake of
confidentiality):

public class GenericModel<PK extends Serializable> {

     protected PK id;

    public PK getId(){
       return id;
    }

    public void setId(PK value){
         this.id = value;
    }
}

and one class like this:

public UF extends GenericModel<Long> {

    private String name;

    //getters and setters
}

The original result map and update statement generated using abator were
like this:

  <resultMap class="UF" id="UFResult">
    <result column="COD_UF" jdbcType="BIGINT" property="id"/>
    <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
  </resultMap>

  <update id="updateByPrimaryKey" parameterClass="UF">
    update uf
    set NAM_UF = #name:VARCHAR#
    where COD_UF = #id:BIGINT#
  </update>

When I tried to use them, I got the same problem you reported. One solution
I found was to specify the java type in each statement using this property.
Changed result map and update statement are here:

  <resultMap class="UF" id="UFResult">
    <result column="COD_UF" jdbcType="BIGINT" property="id"
javaType="long"/>
    <result column="NAM_UF" jdbcType="VARCHAR" property="name"/>
  </resultMap>

  <update id="updateByPrimaryKey" parameterClass="UF">
    update uf
    set NAM_UF = #name:VARCHAR#
    where COD_UF = #id,javaType=long,jdbcType
=BIGINT#
  </update>

After this, everything went fine. But I found this solution a little
cumbersome, since it is not a special type which requires a special type
handler. Anybody has another alternative to this?

Regards.


Vadim Grinshpun wrote:
> 
> Hi all,
> 
> I just ran into an interesting problem, and I'm curious whether I'm 
> doing something wrong, or if it's a known limitation or bug in iBATIS 
> (or its interaction with the JDBC driver?). I'm using iBATIS 2.3.0 with 
> a PostgreSQL's jdbc driver 8.2-504.
> 
> Let's say I have the following classes:
> 
> // wrapper that attaches an attribute to things; a poor-man's mix-in class
> class Wrapper<T>{
>     String wrapperAttribute;
>     T value;
>     String getAttribute() { return wrapperAttribute;}
>     T getValue() { return value; };
>      // remaining bean accessors are defined but not shown
>      // ...
> }
> 
> // a class that uses the  wrapper:
> class FooBean{
>    Wrapper<String> wrappedString;
>    Wrapper<Date> wrappedDate;
>    Wrapper<SomeEnum> wrappedEnum; // Enum and its TypeHandlerCallback 
> are defined elsewhere, not shown
>    // the obvious get/set accessors are defined below, not shown
>    // ...
> }
> // end code
> 
> FooBean is then passed as a parameter to an insert statement, which 
> looks, roughly, along the lines of:
> 
>  <insert ... >
>       INSERT INTO mytable ( string_field, date_field, enum_field )
>       VALUES( #wrappedString.value#,
>                       #wrappedDate.value#,
>                       #wrappedEnum.value# )
>  </insert>
>  
> When trying to run the code, the #wrappedString.value# part of the 
> statement works just fine, but for the #wrappedDate.value# I  get an
> error:
>     "PSQLException: Can't infer the SQL type to use for an instance of 
> java.util.Date. Use setObject() with an explicitly Types value to 
> specify the type to use."
> 
> Seeing this, I tried adding the jdbc type to the parameter map, as shown:
>                       #wrappedDate.value:TIMESTAMP#
> This produced the same exact error.
> 
> Then I tried adding a wrapper method,"Date getWrappedDateValue" which 
> simply calls getWrappedDate().getValue(), and thus returns a Date 
> object, but then I got the same error for the wrappedEnum...
> 
> Can anyone explain this? Is there a way to get this to work properly? I 
> first thought that this has to do with Java's generic not preserving 
> enough information for this to work, but as the error message clearly 
> shows, the type info is retrievable...
> Thanks for any insight!
> 
> -Vadim
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/%22can%27t-infer-the-SQL-type%22-of-a-bean-property-whose-type-is-a-generic-parameter.-tp14956735p14980767.html
Sent from the iBATIS - User - Java mailing list archive at Nabble.com.