You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2023/11/09 14:08:04 UTC
(cayenne) 02/02: CAY-2819 `DataContext.performIteratedQuery()` method should be unified with `iterator()` method
This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit b72b1f4f8be3ee22e09ae4300ff696af6081adf6
Author: stariy95 <st...@gmail.com>
AuthorDate: Thu Nov 9 18:07:33 2023 +0400
CAY-2819 `DataContext.performIteratedQuery()` method should be unified with `iterator()` method
---
RELEASE-NOTES.txt | 1 +
.../org/apache/cayenne/access/DataContext.java | 95 +++++++---------------
.../cayenne/access/DataDomainQueryAction.java | 1 +
.../cayenne/query/IteratedQueryDecorator.java | 17 +++-
4 files changed, 44 insertions(+), 70 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index e1ef21051..8d74cc967 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -41,6 +41,7 @@ CAY-2802 Upgrade Gradle to 7.6.1
CAY-2803 Test infrastructure: declarative custom DI modules in ServerCase
CAY-2805 Stop calling exp parser internally
CAY-2817 Pagination flow refactoring
+CAY-2819 DataContext.performIteratedQuery() method should be unified with iterator() method
Bug Fixes:
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 ec930c81a..4206edfd5 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
@@ -792,84 +792,45 @@ public class DataContext extends BaseContext {
}
- @SuppressWarnings("unchecked")
+ /**
+ * Performs a single database select query returning result as a {@link ResultIterator}.
+ * <p>
+ * It is caller's responsibility to explicitly close the {@link ResultIterator}.
+ * A failure to do so will result in a <b>database connection not being released</b>.
+ * Another side effect of an open {@link ResultIterator} is that an internal Cayenne transaction
+ * that originated in this method stays open until the iterator is closed.
+ * So users should normally close the iterator within the same thread that opened it.
+ * <p>
+ */
@Override
public <T> ResultIterator<T> iterator(final Select<T> query) {
- IteratedQueryDecorator queryDecorator = new IteratedQueryDecorator(query);
- Query queryToRun = nonNullDelegate().willPerformQuery(this, queryDecorator);
- QueryResponse queryResponse = onQuery(this, queryToRun);
- return (ResultIterator<T>) queryResponse.firstIterator();
+ return performIteratedQueryInternal(query, false);
}
/**
- * Performs a single database select query returning result as a
- * ResultIterator. It is caller's responsibility to explicitly close the
- * ResultIterator. A failure to do so will result in a database connection
- * not being released. Another side effect of an open ResultIterator is that
- * an internal Cayenne transaction that originated in this method stays open
- * until the iterator is closed. So users should normally close the iterator
- * within the same thread that opened it.
+ * Performs a single database select query returning result as a {@link ResultIterator}.
+ * <p>
+ * It is caller's responsibility to explicitly close the {@link ResultIterator}.
+ * A failure to do so will result in a <b>database connection not being released</b>.
+ * Another side effect of an open {@link ResultIterator} is that an internal Cayenne transaction
+ * that originated in this method stays open until the iterator is closed.
+ * So users should normally close the iterator within the same thread that opened it.
* <p>
- * Note that 'performIteratedQuery' always returns ResultIterator over
- * DataRows. Use
- * {@link #iterate(Select, org.apache.cayenne.ResultIteratorCallback)} to
- * get access to objects.
+ * Note that {@code performIteratedQuery} always returns {@link ResultIterator} over DataRows.
+ * <p>
+ * Use {@link #iterate(Select, org.apache.cayenne.ResultIteratorCallback)} to get access to objects.
*/
- // TODO: deprecate once all selecting queries start implementing Select<T> interface
@SuppressWarnings({ "rawtypes" })
public ResultIterator performIteratedQuery(Query query) {
-
- 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.
- Transaction tx = getTransactionFactory().createTransaction();
- BaseTransaction.bindThreadTransaction(tx);
-
- ResultIterator<?> result;
- try {
- result = internalPerformIteratedQuery(query);
- } catch (Exception e) {
-
- tx.setRollbackOnly();
- throw new CayenneRuntimeException(e);
- } finally {
-
- // 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 {
- tx.rollback();
- } catch (Exception ignored) {
- }
- }
- }
-
- return new TransactionResultIteratorDecorator<>(result, tx);
- }
+ return performIteratedQueryInternal(query, true);
}
- /**
- * Runs an iterated query in a transactional context provided by the caller.
- */
- ResultIterator <?> internalPerformIteratedQuery(Query query) {
- // note that for now DataChannel API does not support cursors (aka
- // ResultIterator), so we have to go directly to the DataDomain.
- IteratedSelectObserver observer = new IteratedSelectObserver();
- getParentDataDomain().performQueries(Collections.singletonList(query), observer);
- return observer.getResultIterator();
+ @SuppressWarnings("unchecked")
+ private <T> ResultIterator<T> performIteratedQueryInternal(Query query, boolean fetchDataRows) {
+ IteratedQueryDecorator queryDecorator = new IteratedQueryDecorator(query, fetchDataRows);
+ Query queryToRun = nonNullDelegate().willPerformQuery(this, queryDecorator);
+ QueryResponse queryResponse = onQuery(this, queryToRun);
+ return (ResultIterator<T>)queryResponse.firstIterator();
}
/**
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
index e6778c442..22f07a2da 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
@@ -146,6 +146,7 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver {
private boolean interceptIteratedQuery() {
if (query instanceof IteratedQueryDecorator) {
+ noObjectConversion = ((IteratedQueryDecorator) query).isFetchingDataRows();
validateIteratedQuery();
performIteratedQuery();
return DONE;
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/IteratedQueryDecorator.java b/cayenne-server/src/main/java/org/apache/cayenne/query/IteratedQueryDecorator.java
index 9093bd7f9..bbb2e318e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/IteratedQueryDecorator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/IteratedQueryDecorator.java
@@ -21,12 +21,19 @@ package org.apache.cayenne.query;
import org.apache.cayenne.map.EntityResolver;
-public class IteratedQueryDecorator implements Query{
+/**
+ * A simple decorator for an iterated query.
+ * @see org.apache.cayenne.access.DataContext#iterator(Select)
+ * @since 5.0
+ */
+public class IteratedQueryDecorator implements Query {
private final Query query;
+ private final boolean fetchDataRows;
- public IteratedQueryDecorator(Query query) {
+ public IteratedQueryDecorator(Query query, boolean fetchDataRows) {
this.query = query;
+ this.fetchDataRows = fetchDataRows;
}
@Override
@@ -36,7 +43,7 @@ public class IteratedQueryDecorator implements Query{
@Override
public void route(QueryRouter router, EntityResolver resolver, Query substitutedQuery) {
- query.route(router,resolver,substitutedQuery);
+ query.route(router, resolver, substitutedQuery);
}
@Override
@@ -47,4 +54,8 @@ public class IteratedQueryDecorator implements Query{
public Query getQuery() {
return query;
}
+
+ public boolean isFetchingDataRows() {
+ return fetchDataRows;
+ }
}