This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push:
new ae340ed11 CAY-2988 Nested iterated queries transaction handling
ae340ed11 is described below
commit ae340ed11bc7afdde6e0c14940eacd0a91a8bd10
Author: Andrus Adamchik <[email protected]>
AuthorDate: Mon Aug 17 12:44:55 2026 -0400
CAY-2988 Nested iterated queries transaction handling
pushing a test without a fix to see which DBs will fail
---
.../cayenne/access/DataContextIteratedQueryIT.java | 55 ++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java
index 06b3d6ae7..0651c92b5 100644
---
a/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java
+++
b/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java
@@ -26,6 +26,7 @@ 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.tx.TransactionManager;
import org.apache.cayenne.unit.CayenneProjects;
import org.apache.cayenne.unit.CayenneTestsEnv;
import org.junit.jupiter.api.BeforeEach;
@@ -37,6 +38,7 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class DataContextIteratedQueryIT {
@@ -225,4 +227,57 @@ public class DataContextIteratedQueryIT {
// TODO: how do we test that transaction unbound from the thread is
closed/committed at the end?
}
+
+ @Test
+ public void iterator_CallerTransaction() throws Exception {
+ createArtistsDataSet();
+
+ TransactionManager txManager =
env.runtime().getInjector().getInstance(TransactionManager.class);
+
+ int count = txManager.performInTransaction(() -> {
+ int c = 0;
+ try (ResultIterator<Artist> it =
ObjectSelect.query(Artist.class).iterator(context)) {
+ while (it.hasNextRow()) {
+ it.nextRow();
+ c++;
+ }
+ }
+
+ // The caller transaction must survive the iterator, as the
iterator doesn't own it. A committed
+ // transaction would refuse to open a connection for the query
below.
+ assertNotNull(BaseTransaction.getThreadTransaction(), "Caller
transaction was unbound by the iterator");
+ assertEquals(7,
ObjectSelect.query(Artist.class).select(context).size());
+ return c;
+ });
+
+ assertEquals(7, count);
+ }
+
+ @Test
+ public void iterator_NestedIteratorInCallerTransaction() throws Exception {
+ createArtistsAndPaintingsDataSet();
+
+ TransactionManager txManager =
env.runtime().getInjector().getInstance(TransactionManager.class);
+
+ int count = txManager.performInTransaction(() -> {
+ int c = 0;
+ try (ResultIterator<Artist> outer =
ObjectSelect.query(Artist.class).iterator(context)) {
+
+ // open and close a nested iterator over another entity while
"outer" is still open. Closing it
+ // must not commit the caller transaction, as that would close
the "outer" ResultSet as well
+ assertTrue(outer.hasNextRow());
+ try (ResultIterator<Painting> inner =
ObjectSelect.query(Painting.class).iterator(context)) {
+ assertEquals(7, inner.allRows().size());
+ }
+
+ while (outer.hasNextRow()) {
+ outer.nextRow();
+ c++;
+ }
+ }
+ return c;
+ });
+
+ assertEquals(7, count);
+ }
}