To resolve my problem I have added a new attribute; nullValueKeyCol to the
result element. 

This attribute tells iBatis to check for a value in the column referenced in
nullValueKeyCol and if it has a non null value it sets the property to the
null value.

An example may clarify this better.

class A {
        int id;
        B b;
}

class B {
        int id;
        int value;
}

In this example the value column in the table for class B can be null but
never 0 so we encode null as 0. And class A is represented by a table A
which has an id as pk and a bId column which points to a B row and can also
be null.

<resultMap id="A-result" class="A">
        <result property="id" column="id"/>
        <result property="b.id" column="b_id"/>
        <result property="b.value" column="b_value" nullValue="0"/>
</resultMap>

If we do query like this:

select id, b.id as b_id, b.value as b_value from A
left outer join B on A.bId = B.id

For rows where bId is null or has no matching row in B we get a result like
this:

id, null, null

The object we would like to represent this should have b = null. But this is
not the case with iBatis as far as I have seen, instead iBatis creates an
instance of B and sets the value property to 0.

In my work around have I have this resultMap:

<resultMap id="A-result" class="A">
        <result property="id" column="id"/>
        <result property="b.id" column="b_id"/>
        <result property="b.value" column="b_value" nullValue="0"
nullValueKeyCol="b_id" />
</resultMap>

Which tells iBatis the following: If b_value is null check the b_id column,
and if b_id is null let b_value also be null or else set the b_value to the
nullValue.


I don't know if this will be super seeded by some other solution in the
future, but for now it does the trick for me.

Clinton is this something worth checking in to the code base?

Regards Okku

-----Original Message-----
From: Okku [mailto:[EMAIL PROTECTED] 
Sent: den 15 februari 2005 16:26
To: [email protected]; [EMAIL PROTECTED]
Subject: RE: NullValues and complex properties

Thanks for answering.

If I don't use a nullValue it works as expected, but then, of course, I have
to use Integer instead of int.

I tried your solution with a resultMap attribute like this:

<resultMap id="Text-result" class="pim.domain.Text">
        <result property="id" column="textValue_tid_id" />
        <result property="languageId" column="textValue_tid_languageId"
nullValue="0" />
        <result property="value" column="textValue_tid_value" />
</resultMap>

<resultMap id="PropertyValue-result" class="pim.domain.PropertyValue">
        <result property="mediaIdValue" column="mediaIdValue" />
        <result property="id" column="id" />
        <result property="propertyTypeId" column="propertyTypeId" />
        <result property="text" column="textValue_tid_id"
resultMap="PropertyValue.Text-result"/>
</resultMap>


(I had to prefix the resultmap with the current namespace or else iBatis
didn't found it.)

--- The error occurred in sqlMaps/PropertyValue.xml.  
--- The error occurred while applying a result map.  
--- Check the PropertyValue.PropertyValue-result.  
--- The error happened while setting a property on the result object.  
--- Cause: com.ibatis.sqlmap.client.SqlMapException: Error instantiating
collection property for mapping 'text'.  Cause: java.lang.ClassCastException
Caused by: java.lang.ClassCastException

The row that seems to throw the exception is:

  try {
    c = (Collection) type.newInstance();   <----
  } catch (Exception e) {
    throw new SqlMapException("Error instantiating collection property for
mapping '" + mapping.getPropertyName() + "'.  Cause: " + e, e);
  }

It seems that iBatis is trying to cast the text object to a Collection? Is
this correct?

Reagards Okku


-----Original Message-----
From: Clinton Begin [mailto:[EMAIL PROTECTED] 
Sent: den 11 februari 2005 01:29
To: [email protected]
Subject: Re: NullValues and complex properties

What happens if you don't use a nullValue?

Also, you could make use of the new resultMap attribute to manage the
complex relationship:

<result property="text" column="textValue_tid_id" resultMap="Text-result"/>

And then map all of the text properties in that result map.

Cheeers,
Clinton

On Thu, 10 Feb 2005 13:48:07 +0100, Okku <[EMAIL PROTECTED]> wrote:
> We have a lot of tables with pk:s of type int.
> 
> Some of the references to these table id:s can be null, since it is
> convenient to have the same type we use int everywhere, and since no ids
in
> our database can have the value 0 we set the nullValue to 0.
> 
> This works well on classes without complex properties.
> 
> But for a resultmap like this:
> 
> <resultMap id="PropertyValue-result" class="pim.domain.PropertyValue">
>       <result property="mediaIdValue" column="mediaIdValue" />
>         <result property="id" column="id" />
>         <result property="propertyTypeId" column="propertyTypeId" />
>         <result property="text.id" column="textValue_tid_id" />
>         <result property="text.languageId"
column="textValue_tid_languageId"
> nullValue="0" />
>         <result property="text.value" column="textValue_tid_value" />
> </resultMap>
> 
> Where we use a complex type text and one of the properties languageId can
be
> null we get some strange behavior.
> 
> What we want is that the text property to be null if textValue_tid_id,
> textValue_tid_languageId and textValue_tid_value is null, but instead
iBatis
> creates a new text property object and sets the languageId to 0.
> 
> Is this the correct behavior?
> 
> Regards Okku Touronen
> 
>






Reply via email to