[ 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.