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.