mybatis / old-google-code-issues

Automatically exported from code.google.com/p/mybatis
2 stars 4 forks source link

Lazy loads do not execute within Spring-managed transactions #279

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What version of the MyBatis are you using?
3.0.4

Please describe the problem.  Unit tests are best!
If a lazy load query executes while there is an active Spring-managed 
transaction, the query does not execute within the transaction. The query will 
only participate in the current transaction if ResultLoader.newExecutor() 
retrieves the Connection by calling 
org.springframework.jdbc.datasource.DataSourceUtils.getConnection(ds) instead 
of ds.getConnection(). Presumably mybatis-guice has the same problem. This 
could be fixed by modifying the TransactionFactory interface so that it 
retrieves the Connection in addition to the Transaction.

What is the expected output? What do you see instead?
Here is a scenario that can reproduce this problem:
1. Delete row from table A.
2. Within the same transaction boundary, lazy load a collection from table A. 
Lazy loaded result will contain the deleted row but it should not.

Please provide any additional information below.
See comments in Issue 247.

Original issue reported on code.google.com by patrick....@3pillarglobal.com on 22 Mar 2011 at 5:34

GoogleCodeExporter commented 9 years ago
Just for the record, let me copy my reply in this issue:

You are right Patrick. We already discussed that limitation in the dev list.

MyBatis transaction interface should also include the connection retrieval. So 
the full connection livecycle can be managed by a plugin. 

I don think this will be addressed in a short time. 

Anyway this should not be a common problem.

Original comment by eduardo.macarron on 23 Apr 2011 at 8:16

GoogleCodeExporter commented 9 years ago
I have had a look again to this issue to see if there is something we can do 
for MyBatis 3.1

At the first time I thought that Transaction interface was wrong because it 
should manage the whole connection lifecycle, included its creation. But after 
thinking a bit more about this I think MyBatis is OK because connection 
creation is already covered by DataSource.

So DataSource provides connections and Transaction handles them. Sounds OK. And 
in that case this issue becomes again a MyBatis-Spring issue.

The only way I can think to solve this is to provide our own datasource that 
picks connections from Spring's TransactionManager 
(DataSourceUtils.getConnection).

Patch provided. Don't know if it is worth including this change just to cover 
the lazy load scenario.

Original comment by eduardo.macarron on 5 Jul 2011 at 7:51

Attachments:

GoogleCodeExporter commented 9 years ago
My understanding with getting connection from DataSource if you're using Spring 
is to always get the connection using DataSourceUtils.getConnection and return 
(do not close) the connection using DataSourceUtils.releaseConnection. With 
these 2 methods, Spring will check if there is any transaction opened within 
the same thread or otherwise it will create new.
If MyBatis is configured using Spring, then I believe 
DataSourceUtils.getConnection should be used. However if it does not used 
within Spring, DataSource.getConnection should be used. Not sure if it runs 
within Guice.

Original comment by winarto on 28 Aug 2011 at 2:55

GoogleCodeExporter commented 9 years ago
Fix proposal in issue 382. Still has to be disussed and may hopefully go in 
3.l.0

Original comment by eduardo.macarron on 11 Sep 2011 at 4:07

GoogleCodeExporter commented 9 years ago

Original comment by eduardo.macarron on 26 Nov 2011 at 6:17

GoogleCodeExporter commented 9 years ago
Fixed both in MyBatis & MyBatis-Spring. See r4045.

Original comment by eduardo.macarron on 29 Nov 2011 at 9:26

GoogleCodeExporter commented 9 years ago

Original comment by eduardo.macarron on 29 Nov 2011 at 9:27