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