ibatis-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kai Grabfelder (JIRA)" <ibatis-...@incubator.apache.org>
Subject [jira] Commented: (IBATIS-466) Incorrect behaviour when combining RowHandler with groupBy
Date Fri, 17 Apr 2009 16:43:14 GMT

    [ https://issues.apache.org/jira/browse/IBATIS-466?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12700236#action_12700236
] 

Kai Grabfelder commented on IBATIS-466:
---------------------------------------

here is what I would do:
- make sure the query returns the data sorted correctly (e.g. sort by the columns used for
grouping). In the above example the sorting should look like ORDER BY person_id asc
- use a rowhandler, but no iBatis groupBy functionality
- do the groupBy functionality in your rowhandler, just you would do in plain old JDBC (continue
to add albumbs to a person as long as the person_id does not change)

> Incorrect behaviour when combining RowHandler with groupBy
> ----------------------------------------------------------
>
>                 Key: IBATIS-466
>                 URL: https://issues.apache.org/jira/browse/IBATIS-466
>             Project: iBatis for Java
>          Issue Type: Bug
>          Components: SQL Maps
>    Affects Versions: 2.3.0
>            Reporter: William Shields
>
> Assuming:
> CREATE TABLE Person {
>   person_id NUMBER PRIMARY KEY,
>   name VARCHAR2(100)
> )
> CREATE TABLE Album (
>   album_id NUMBER PRIMARY KEY,
>   owner NUMBER REFERENCES (Person.person_id),
>   name VARCHAR2(100)
> )
> and
> public class Person {
>   private long personId;
>   private String name;
>   private List<Album> albums;
>   ...
> }
> public class Album {
>   private long albumId;
>   private long owner;
>   private String name;
>   ...
> }
> with query:
> <resultMap id="album" class="Abum">
>   <result property="albumId" column="ALBUM_ID"/>
>   <result property="owner" column="PERSON_ID"/>
>   <result property="name" column="ALBUM_NAME"/>
> </resultMap>
> <resultMap id="person" class="Person" groupBy="personId">
>   <result property="personId" column="PERSON_ID"/>
>   <result property="name" column="PERSON_NAME"/>
>   <result property="albums" resultMap="album"/>
> </resultMap>
> <select id="selectAlbums" resultMap="person">
>   SELECT person_id, p.name person_name, album_id, a.name album_name
>   FROM Person p, Album a
>   WHERE person_id = owner
> </select>
> with data:
> Person:
> 1 John
> 2 Mary
> Album:
> 10 1 "Bat Out Of Hell"
> 11 2 "The Wall"
> 12 2 "Eyes Open"
> 12 2 "White Ladder"
> Now, queryForList() works correctly.  Two Person objects are returned.  The first (John)
has 1 album, Mary has 3.  If instead you do:
> queryWithRowHandler("....selectAlbums", new RowHandler() {
>   public void handleRow(Object valueObject) {
>     Person p = (Person)valueObject;
>     System.out.println(p.getName() + " has " + p.getAlbums().size() + " albums");
>   }
> }
> It displays 1 for each of the two rows.  The RowHandler is being called on the first
row and then it continues to add to the sub-list.  This is a real problem if you want to process
the fully loaded value object.  I've come up with this workaround:
> public interface TypedRowHandler<T> {
>   void handle(T t);
> }
> public class CleverRowHandler<T> implements RowHandler {
>   TypedRowHandler<T> handler;
>   private T last;
>   public CleverRowHandler(TypedRowHandler<T> handler) {
>     this.handler = handler;
>   }
>   public void handleRow(Object valueObject) {
>     flush();
>     last = (T)valueObject;
>   }
>   public void flush() {
>     if (last != null) {
>       handler.handler(last);
>     }
>     last = null;
>   }
> }
> with DAO code:
> public void processPersons() {
>   CleverRowHandler<Person> rh = new CleverRowHandler<T>(new TypedRowHandler<Person>()
{
>     public void handle(Person p) {
>       // do whatever
>     }
>   };
>   try {
>     getSqlMapClientTemplate().queryWithRowHandler("....selectPersons", rh);
>   } finally {
>     rh.flush();
>   }
> }
> but that's rather messy.  I believe that the current behaviour is a bug and introduces
potential threading issues (in my case my row handler creates a Runnable and submits it to
a ExecutorService, which is a problem if ibatis is still adding objects to the sub-list).

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


Mime
View raw message