You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/08/17 16:54:29 UTC

(cayenne) branch master updated: CAY-2988 Nested iterated queries transaction handling

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 <an...@objectstyle.com>
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);
+    }
 }