Repository: cayenne Updated Branches: refs/heads/master 03b0d270d -> 5838101e5
CAY-2111 Unbind transaction object from the current thread for iterated queries Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/d8e5afec Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/d8e5afec Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/d8e5afec Branch: refs/heads/master Commit: d8e5afec9236bfdda3469ba0eb69e33d8fa28a62 Parents: 03b0d27 Author: Andrus Adamchik <[email protected]> Authored: Mon Sep 5 14:28:37 2016 +0300 Committer: Andrus Adamchik <[email protected]> Committed: Mon Sep 5 14:37:00 2016 +0300 ---------------------------------------------------------------------- .../org/apache/cayenne/access/DataContext.java | 24 ++++++++++++-------- .../TransactionResultIteratorDecorator.java | 13 ++++------- .../access/DataContextIteratedQueryIT.java | 13 +++++++++++ 3 files changed, 32 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/d8e5afec/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java index 05186ab..a88ed6b 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java @@ -874,14 +874,16 @@ public class DataContext extends BaseContext { // interface @SuppressWarnings({ "rawtypes" }) public ResultIterator performIteratedQuery(Query query) { - // TODO: use 4.0 TransactionManager + if (BaseTransaction.getThreadTransaction() != null) { return internalPerformIteratedQuery(query); } else { + + // can't use TransactionManger here as it would attempt to commit the transaction at the end... + // manually manage a transaction, so that a ResultIterator wrapper - // could close - // it when it is done. + // could close it when it is done. Transaction tx = getTransactionFactory().createTransaction(); BaseTransaction.bindThreadTransaction(tx); @@ -889,15 +891,19 @@ public class DataContext extends BaseContext { try { result = internalPerformIteratedQuery(query); } catch (Exception e) { - BaseTransaction.bindThreadTransaction(null); + tx.setRollbackOnly(); throw new CayenneRuntimeException(e); } finally { - // note: we are keeping the transaction bound to the current - // thread on - // success - iterator will unbind it. Unsetting a transaction - // here would - // result in some strangeness, at least on Ingres + + // unbind thread tx before returning to the caller. Transaction will be managed internally by the + // ResultIterator and should not get in the way of other DB operations that may be performed + // within the iterator.... + + // TODO: there was an older comment about Ingres breaking when we unbind thread transaction + // before closing the iterator. As we have no test environment for ingres, we can't + // confirm this here... + BaseTransaction.bindThreadTransaction(null); if (tx.isRollbackOnly()) { try { http://git-wip-us.apache.org/repos/asf/cayenne/blob/d8e5afec/cayenne-server/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java index a14281d..b269f8d 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java @@ -19,15 +19,14 @@ package org.apache.cayenne.access; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.ResultIterator; -import org.apache.cayenne.tx.BaseTransaction; import org.apache.cayenne.tx.Transaction; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * Decorates ResultIterator to close active transaction when the iterator is * closed. @@ -65,10 +64,6 @@ final class TransactionResultIteratorDecorator<T> implements ResultIterator<T> { } throw new CayenneRuntimeException(e); - } finally { - if (BaseTransaction.getThreadTransaction() == tx) { - BaseTransaction.bindThreadTransaction(null); - } } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/d8e5afec/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java index ba35c5d..e630e46 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java @@ -28,6 +28,7 @@ import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.testdo.testmap.Painting; +import org.apache.cayenne.tx.BaseTransaction; import org.apache.cayenne.unit.di.server.CayenneProjects; import org.apache.cayenne.unit.di.server.ServerCase; import org.apache.cayenne.unit.di.server.UseServerRuntime; @@ -38,6 +39,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class DataContextIteratedQueryIT extends ServerCase { @@ -228,4 +230,15 @@ public class DataContextIteratedQueryIT extends ServerCase { assertEquals(14, tPainting.getRowCount()); } + + @Test + public void testPerformIteratedQuery_Transaction() throws Exception { + createArtistsDataSet(); + + try (ResultIterator<?> it = context.performIteratedQuery(SelectQuery.query(Artist.class));) { + assertNull(BaseTransaction.getThreadTransaction()); + } + + // TODO: how do we test that transaction unbound from the thread is closed/committed at the end? + } }
