Loading Polymorphic List Properties with a Discriminator and "groupBy" (Bug?)
-----------------------------------------------------------------------------

                 Key: IBATIS-420
                 URL: https://issues.apache.org/jira/browse/IBATIS-420
             Project: iBatis for Java
          Issue Type: Improvement
          Components: SQL Maps
    Affects Versions: 2.3.0
            Reporter: Daniel Carleton


Consider the following scenario.

You've written a class called Container, and you're trying to load an instance 
of it from the database using SQL Maps.  Container has an ArrayList<SuperClass> 
typed property named "list," which will be loaded with instances of Foo and 
Bar, both subclasses of SuperClass.  Container instances are represented by 
rows in a table called "containers," and Foo and Bar in tables "foos" and 
"bars" respectively.

So, you create the following sqlMap with the hope that it achieves your aims.

<sqlMap namespace="Example">
        <resultMap class="Container" id="root" groupBy="id">
                <result property="id" column="id"/>
                <discriminator javaType="String" column="entity_type">
                        <subMap value="foo" resultMap="fooSub"/>
                        <subMap value="bar" resultMap="barSub"/>
                </discriminator>
        </resultMap>
        <resultMap id="fooSub" class="Container" extends="root">
                <result property="list" resultMap="fooMap"/>
        </resultMap>
        <resultMap id="barSub" class="Container" extends="root">
                <result property="list" resultMap="barMap"/>
        </resultMap>
        <resultMap id="fooMap" class="Foo">
                <result property="id" column="id">
                <result property="name" column="name">
        </resultMap>
        <resultMap id="barMap" class="Bar">
                <result property="id" column="id">
                <result property="name" column="name">
        </resultMap>
        <statement id="getContainer" resultMap="root">
                SELECT containers.id_container,
                        foos.id, foos.name, bars.id, bars.name,
                        CASE
                        WHEN foos.id IS NULL THEN 'foo'
                        WHEN bars.id IS NULL THEN 'bar'
                        END AS entity_type

                FROM containers
                        LEFT JOIN foos USING(id_container)
                        LEFT JOIN bars USING(id_container)
                WHERE containers.id_container = 1
                        AND ( foos.id IS NOT NULL OR bars.id IS NOT NULL)
        </statement>    
</sqlMap>

What you get back, however, is a list of Container instances rather than a 
single object.  Each instance's "list" property is populated with only one of 
Foo or Bar instances.

The problem is that a new Container instance is created each time a different 
subMap is delegated to.  Cached instances of Container for unique values of the 
"groupBy" column are stored per-ResultMap, and so each time we switch our 
ResultMap from fooSub to barSub, or from barSub to fooSub, we lose the instance 
of container we were working on and start a new one.

This can be seen happening at the location below.

com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.setResultObjectValues

Please also note the following thread.

http://www.mail-archive.com/[EMAIL PROTECTED]/msg08457.html

I'm going to do an unpleasant work-around involving a RowHandler for now.

Thanks for considering this.

Cheers,

- Daniel


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to