[ http://issues.apache.org/jira/browse/IBATIS-162?page=all ]
     
Clinton Begin resolved IBATIS-162:
----------------------------------

    Resolution: Won't Fix
     Assign To: Clinton Begin


Having looked at this, I think the best solution for this type or requirement 
is to use a second instance of the SqlMapClient.  The first for the outer read 
of the large data set, and the second for the writes.  Or, you might be able to 
achieve a similar effect by explicitly opening two sessions, again, one being 
for the outer read, the other being for the writes.  That will give you the 
most control over how wide the transaction scope is.

> Unexpected behavior in RowHandler method when doing a nested query causing 
> closed connection objects
> ----------------------------------------------------------------------------------------------------
>
>          Key: IBATIS-162
>          URL: http://issues.apache.org/jira/browse/IBATIS-162
>      Project: iBatis for Java
>         Type: Bug
>   Components: SQL Maps
>     Versions: 2.1.0
>     Reporter: Jayson Minard
>     Assignee: Clinton Begin

>
> as explained in a message between our engineering staff, when you perform a 
> nested query in iBatis during a handleRow() method, the closure of the 
> connection object terminates the outer query.  It only works in the default 
> iBatis connection pool due to what appears to be dangerous behavior.  
> Misunderstanding, or real bug?  See full explaination below:
> --- snip ---
> If you just want the summary, here it is: Don't use RowHandler's with your 
> iBATIS select queries.  If you want to know why, feel free to read on.
>  
> When using iBATIS, you have the option of providing a RowHandler to the query 
> selection method, which will apply the same code to every row returned in the 
> result set.  To describe it better, here's a sample of how the code normally 
> works and then how it might work with a row handler.
>  
> NO ROW HANDLER:
>    1. Submit select query
>    2. Get a connection from the pool, if you have not explicitly started a 
> transaction
>    3. A prepared statement and result set are created implicitly
>    4. Iterate through result set
>       a) Place each object produced into a list
>    5. Close the previously created prepared statement and result set
>    6. Return the connection to the pool, if you have not explicitly started a 
> transaction
>    7. Return the list to the calling method
>    8. Iterate through the resulting list
>        a) Apply processing to each object
>  
>  
> WITH ROW HANDLER
>    1. Submit select query
>    2. Get a connection from the pool and start an implicit transaction, if 
> you have not explicitly started a transaction
>    3. A prepared statement and result set are created implicitly
>    4. Iterate through result set
>       a) Apply processing to each object as the result set is read
>          -- The handler accepts the result object and the result list.  You 
> can do any processing you wish and add (or not add) anything you want to the 
> List
>          -- This may include another database query 
>    5. Close the previously created prepared statement and result set
>    6. Commit the implicit transaction and return the connection to the pool, 
> if you have not explicitly started a transaction
>    7. Return the list to the calling method
>    8. Use or ignore the list, depending on the process
>  
>  
> Alot of people have varying opinions as to which is the better methodology.  
> Some people might be prone to use RowHandler's because they give more of an 
> OOP approach.  This is all fine, diversity is a good thing. Now here's the 
> problem with RowHandler approach used in iBATIS:
>  
> Let's say you haven't explicitly started a transaction and your 
> RowHandler.handleRow() method performs a query of its own.  Here's what will 
> happen with the first record:
>  
>   1. iBATIS calls next() on the result set
>   2. The result object is passed to the rowHandler
>   3. The row handler submits a query
>   4. An implicit transaction is started
>   5. The query is processed
>   6. The implicit transaction is commited and the connection returned to the 
> pool
>   7. iBATIS calls next() on the result set, which is no longer valid because 
> the connection has been return to the pool
>  
>  
> You cannot continue to use a result set or statement belonging to a 
> connection that has been returned to the pool, this is bad form.  In the case 
> of the Abebooks connection pool, an exception will actually be thrown, 
> because the connection is treated as having been closed by the connection 
> pool data source.
>  
> So why didn't this issue make itself known when we were using the connection 
> pool?  The iBATIS connection pool behaves a bit differently, as they just 
> have a flag external to the connection indicating that it is returned to the 
> pool.  This prevents any new statements from being created against the 
> connection.  However, since close() is not called, the result set doesn't 
> know that the connection is invalid.  For this reason, the code was able to 
> sort of get away with this type of behaviour, though it did provide a risk of 
> unusial behaviour.
>  
> So, in summary, the moral of the story is to avoid using RowHandlers with 
> iBATIS.  I'll add something to our confluence pages on this.
>  

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to