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
commit 42af71bd20c07987d9f5a3440af646ca54ab80f9 Author: Andrus Adamchik <[email protected]> AuthorDate: Sun Aug 30 11:15:58 2026 -0400 CAY-3005 ResultIterator.allRows() does not convert to DataObjects --- RELEASE-NOTES.txt | 1 + .../org/apache/cayenne/access/DataContext.java | 106 ++++++++++----------- .../access/ResultIteratorConverterDecorator.java | 4 +- .../cayenne/access/DataContextIteratedQueryIT.java | 43 +++++++++ .../org/apache/cayenne/access/EmbeddingIT.java | 16 ++++ 5 files changed, 111 insertions(+), 59 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index ec13dfd55..391fe3fbc 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -23,6 +23,7 @@ CAY-2999 Modeler: A restricted method in java.lang.System has been called CAY-3001 Modeler: Auto-increment attribute is not picked up CAY-3002 Modeler: NPE after clicking path chooser CAY-3003 Modeler: NPE editing unmapped ObjAttribute +CAY-3005 ResultIterator.allRows() doesn't convert to DataObjects ---------------------------------- Release: 5.0-M3 diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java index abe3ba770..9d5d8fb01 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java @@ -96,9 +96,9 @@ public class DataContext implements ObjectContext { /** * Returns the ObjectContext bound to the current thread. * - * @since 3.0 * @return the ObjectContext associated with caller thread. * @throws IllegalStateException if there is no ObjectContext bound to the current thread. + * @since 3.0 * @deprecated if you are using thread context, you can create your own ThreadLocal */ @Deprecated(since = "5.0", forRemoval = true) @@ -162,7 +162,7 @@ public class DataContext implements ObjectContext { /** * Creates a new DataContext with parent DataChannel and ObjectStore. - * + * * @since 1.2 */ public DataContext(DataChannel channel, ObjectStore objectStore) { @@ -198,7 +198,7 @@ public class DataContext implements ObjectContext { * following deserialization. * * @return true if the context successfully attached to the thread runtime, - * false - if it was already attached. + * false - if it was already attached. * @since 3.1 */ protected boolean attachToRuntimeIfNeeded() { @@ -299,7 +299,7 @@ public class DataContext implements ObjectContext { /** * Returns a DataDomain used by this DataContext. DataDomain is looked up in the DataChannel hierarchy. If the final * channel is not a DataDomain, null is returned. - * + * * @return DataDomain that is a direct or indirect parent of this DataContext in the DataChannel hierarchy. * @since 1.1 */ @@ -321,7 +321,7 @@ public class DataContext implements ObjectContext { * Sets a DataContextDelegate for this context. Delegate is notified of * certain events in the DataContext lifecycle and can customize DataContext * behavior. - * + * * @since 1.1 */ public void setDelegate(DataContextDelegate delegate) { @@ -330,7 +330,7 @@ public class DataContext implements ObjectContext { /** * Returns a delegate currently associated with this DataContext. - * + * * @since 1.1 */ public DataContextDelegate getDelegate() { @@ -339,8 +339,8 @@ public class DataContext implements ObjectContext { /** * @return a delegate instance if it is initialized, or a shared noop - * implementation the context has no delegate. Useful to prevent - * extra null checks and conditional logic in the code. + * implementation the context has no delegate. Useful to prevent + * extra null checks and conditional logic in the code. * @since 1.1 */ DataContextDelegate nonNullDelegate() { @@ -426,7 +426,7 @@ public class DataContext implements ObjectContext { /** * Returns a collection of all uncommitted registered objects. - * + * * @since 1.2 */ @Override @@ -595,7 +595,7 @@ public class DataContext implements ObjectContext { /** * Converts a list of DataRows to a List of Persistent registered with this * DataContext. - * + * * @since 3.0 */ public List objectsFromDataRows(ClassDescriptor descriptor, List<? extends DataRow> dataRows) { @@ -608,13 +608,13 @@ public class DataContext implements ObjectContext { return new ObjectResolver(this, descriptor, true).synchronizedObjectsFromDataRows(dataRows); } - private List <?> objectsFromDataRowsFromParentContext(ClassDescriptor descriptor, List<? extends DataRow> dataRows) { + private List<?> objectsFromDataRowsFromParentContext(ClassDescriptor descriptor, List<? extends DataRow> dataRows) { return getParent().onQuery(this, new ObjectsFromDataRowsQuery(descriptor, dataRows)).firstList(); } /** * Creates a Persistent from DataRow. - * + * * @see DataRow * @since 3.1 */ @@ -633,7 +633,7 @@ public class DataContext implements ObjectContext { /** * Creates a Persistent from DataRow. This variety of the * 'objectFromDataRow' method is normally used for generic classes. - * + * * @see DataRow * @since 3.1 * @since 5.0 returns {@link Persistent} instead of the deprecated DataObject @@ -647,7 +647,7 @@ public class DataContext implements ObjectContext { /** * Creates and registers a new persistent object. - * + * * @since 1.2 */ @Override @@ -673,7 +673,7 @@ public class DataContext implements ObjectContext { * <i>Note: in most cases {@link #newObject(Class)} method should be used, * however this method is helpful when generic persistent classes are * used.</i> - * + * * @since 3.0 */ public Persistent newObject(String entityName) { @@ -706,9 +706,8 @@ public class DataContext implements ObjectContext { * relationships. * <p> * <i>Note that since 3.0 this method takes Object as an argument instead of a {@link Persistent}.</i> - * - * @param object - * new object that needs to be made persistent. + * + * @param object new object that needs to be made persistent. */ @Override public void registerNewObject(Object object) { @@ -828,7 +827,7 @@ public class DataContext implements ObjectContext { /** * Unregisters a Collection of Persistent objects from the DataContext and the underlying ObjectStore. * This operation also unsets DataContext for each object and changes its state to {@link PersistenceState#TRANSIENT} - * + * * @see #invalidateObjects(Collection) */ public void unregisterObjects(Collection<?> objects) { @@ -867,7 +866,7 @@ public class DataContext implements ObjectContext { * If the parent channel is a DataContext, reverts local changes to make * this context look like the parent, if the parent channel is a DataDomain, * reverts all changes. - * + * * @since 1.2 */ @Override @@ -911,9 +910,9 @@ public class DataContext implements ObjectContext { * changes, without a database update. If it is a DataDomain (the most * common case), the changes are written to the database. To cause cascading * commit all the way to the database, one must use {@link #commitChanges()} . - * - * @since 1.2 + * * @see #commitChanges() + * @since 1.2 */ @Override public void commitChangesToParent() { @@ -950,7 +949,7 @@ public class DataContext implements ObjectContext { /** * Synchronizes with the parent channel, performing a flush or a commit. - * + * * @since 1.2 */ GraphDiff flushToParent(boolean cascade) { @@ -1096,11 +1095,11 @@ public class DataContext implements ObjectContext { * <p> * Note that {@code performIteratedQuery} always returns {@link ResultIterator} over DataRows. * <p> - * Use {@link #iterate(Select, org.apache.cayenne.ResultIteratorCallback)} to get access to objects. + * * @deprecated in favor of {@link #iterator(Select)}. */ @Deprecated(since = "5.0", forRemoval = true) - @SuppressWarnings({ "rawtypes" }) + @SuppressWarnings({"rawtypes"}) public ResultIterator performIteratedQuery(Query query) { return performIteratedQueryInternal(query, true); } @@ -1110,12 +1109,12 @@ public class DataContext implements ObjectContext { IteratedQueryDecorator queryDecorator = new IteratedQueryDecorator(query, fetchDataRows); Query queryToRun = nonNullDelegate().willPerformQuery(this, queryDecorator); QueryResponse queryResponse = onQuery(this, queryToRun); - return (ResultIterator<T>)queryResponse.firstIterator(); + return (ResultIterator<T>) queryResponse.firstIterator(); } /** * Executes a query returning a generic response. - * + * * @since 1.2 */ @Override @@ -1148,10 +1147,10 @@ public class DataContext implements ObjectContext { * <p> * <i>Since 1.2 takes any Query parameter, not just GenericSelectQuery</i> * </p> - * + * * @return A list of Persistent objects or a DataRows, depending on the value - * returned by {@link QueryMetadata#isFetchingDataRows()}. - * Сan also return an iterator if the query is an instance of iteratedQuery. + * returned by {@link QueryMetadata#isFetchingDataRows()}. + * Сan also return an iterator if the query is an instance of iteratedQuery. */ @Override public List performQuery(Query query) { @@ -1167,7 +1166,7 @@ public class DataContext implements ObjectContext { /** * An implementation of a {@link DataChannel} method that is used by child * contexts to execute queries. Not intended for direct use. - * + * * @since 1.2 */ public QueryResponse onQuery(ObjectContext context, Query query) { @@ -1196,7 +1195,7 @@ public class DataContext implements ObjectContext { /** * Performs a single database query that does not select rows. Returns an * array of update counts. - * + * * @since 1.1 */ public int[] performNonSelectingQuery(Query query) { @@ -1207,7 +1206,7 @@ public class DataContext implements ObjectContext { /** * Performs a named mapped query that does not select rows. Returns an array * of update counts. - * + * * @since 1.1 */ public int[] performNonSelectingQuery(String queryName) { @@ -1217,7 +1216,7 @@ public class DataContext implements ObjectContext { /** * Performs a named mapped non-selecting query using a map of parameters. * Returns an array of update counts. - * + * * @since 1.1 */ public int[] performNonSelectingQuery(String queryName, Map<String, ?> parameters) { @@ -1229,14 +1228,12 @@ public class DataContext implements ObjectContext { * the DataMaps. Internally Cayenne uses a caching policy defined in the * named query. If refresh flag is true, a refresh is forced no matter what * the caching policy is. - * - * @param queryName - * a name of a GenericSelectQuery defined in one of the DataMaps. - * If no such query is defined, this method will throw a - * CayenneRuntimeException. - * @param expireCachedLists - * A flag that determines whether refresh of <b>cached lists</b> - * is required in case a query uses caching. + * + * @param queryName a name of a GenericSelectQuery defined in one of the DataMaps. + * If no such query is defined, this method will throw a + * CayenneRuntimeException. + * @param expireCachedLists A flag that determines whether refresh of <b>cached lists</b> + * is required in case a query uses caching. * @since 1.1 */ public List<?> performQuery(String queryName, boolean expireCachedLists) { @@ -1248,19 +1245,16 @@ public class DataContext implements ObjectContext { * the DataMaps. Internally Cayenne uses a caching policy defined in the * named query. If refresh flag is true, a refresh is forced no matter what * the caching policy is. - * - * @param queryName - * a name of a GenericSelectQuery defined in one of the DataMaps. - * If no such query is defined, this method will throw a - * CayenneRuntimeException. - * @param parameters - * A map of parameters to use with stored query. - * @param expireCachedLists - * A flag that determines whether refresh of <b>cached lists</b> - * is required in case a query uses caching. + * + * @param queryName a name of a GenericSelectQuery defined in one of the DataMaps. + * If no such query is defined, this method will throw a + * CayenneRuntimeException. + * @param parameters A map of parameters to use with stored query. + * @param expireCachedLists A flag that determines whether refresh of <b>cached lists</b> + * is required in case a query uses caching. * @since 1.1 */ - public List<?> performQuery(String queryName, Map <String,?>parameters, boolean expireCachedLists) { + public List<?> performQuery(String queryName, Map<String, ?> parameters, boolean expireCachedLists) { return (List<?>) performQuery(expireCachedLists ? MappedSelect.query(queryName).params(parameters).forceNoCache() : MappedSelect.query(queryName).params(parameters)); @@ -1269,7 +1263,7 @@ public class DataContext implements ObjectContext { /** * Returns <code>true</code> if the ObjectStore uses shared cache of a * parent DataDomain. - * + * * @since 1.1 */ public boolean isUsingSharedSnapshotCache() { @@ -1329,7 +1323,7 @@ public class DataContext implements ObjectContext { /** * Returns this context's ObjectStore. - * + * * @since 1.2 */ @Override @@ -1341,7 +1335,7 @@ public class DataContext implements ObjectContext { * An internal version of {@link #localObject(Persistent)} that operates on * ObjectId instead of Persistent, and wouldn't attempt to look up an object * in the parent channel. - * + * * @since 3.1 */ Persistent findOrCreateObject(ObjectId id) { diff --git a/cayenne/src/main/java/org/apache/cayenne/access/ResultIteratorConverterDecorator.java b/cayenne/src/main/java/org/apache/cayenne/access/ResultIteratorConverterDecorator.java index 08fb54380..9fdd42d71 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/ResultIteratorConverterDecorator.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/ResultIteratorConverterDecorator.java @@ -37,9 +37,7 @@ class ResultIteratorConverterDecorator<T, R> implements ResultIterator<R> { @SuppressWarnings("unchecked") @Override public List<R> allRows() { - List<T> mainRows = iterator.allRows(); - converter.convert(mainRows); - return (List<R>) mainRows; + return (List<R>) converter.convert(iterator.allRows()); } @Override 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 0651c92b5..23cd3425e 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextIteratedQueryIT.java @@ -181,6 +181,49 @@ public class DataContextIteratedQueryIT { } } + @Test + public void iteratorAllRows() throws Exception { + createArtistsDataSet(); + + try (ResultIterator<Artist> it = context.iterator(ObjectSelect.query(Artist.class))) { + List<Artist> rows = it.allRows(); + + assertEquals(7, rows.size()); + for (Artist a : rows) { + assertNotNull(a.getArtistName()); + } + } + } + + @Test + public void iteratorAllRows_DataRows() throws Exception { + createArtistsDataSet(); + + try (ResultIterator<DataRow> it = context.iterator(ObjectSelect.dataRowQuery(Artist.class))) { + List<DataRow> rows = it.allRows(); + + assertEquals(7, rows.size()); + for (DataRow row : rows) { + assertNotNull(row.get("ARTIST_NAME")); + } + } + } + + @Test + public void iteratorAllRows_Scalars() throws Exception { + createArtistsDataSet(); + + try (ResultIterator<String> it = context + .iterator(ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME))) { + List<String> rows = it.allRows(); + + assertEquals(7, rows.size()); + for (String name : rows) { + assertNotNull(name); + } + } + } + @Test public void contextIterator() throws Exception { createArtistsAndPaintingsDataSet(); diff --git a/cayenne/src/test/java/org/apache/cayenne/access/EmbeddingIT.java b/cayenne/src/test/java/org/apache/cayenne/access/EmbeddingIT.java index cb3528726..16f5f5065 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/EmbeddingIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/EmbeddingIT.java @@ -21,6 +21,7 @@ package org.apache.cayenne.access; import org.apache.cayenne.DataRow; import org.apache.cayenne.PersistenceState; import org.apache.cayenne.ResultBatchIterator; +import org.apache.cayenne.ResultIterator; import org.apache.cayenne.query.ObjectSelect; import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.embeddable.EmbedChild; @@ -353,6 +354,21 @@ public class EmbeddingIT { env.context().commitChanges(); } + @Test + public void columnSelectIteratorAllRows() throws Exception { + createSelectDataSet2(); + + try (ResultIterator<Embeddable1> it = ObjectSelect.columnQuery(EmbedEntity1.class, EmbedEntity1.EMBEDDED2) + .orderBy(EmbedEntity1.EMBEDDED2.dot(Embeddable1.EMBEDDED10).asc()) + .iterator(env.context())) { + + List<Embeddable1> result = it.allRows(); + assertEquals(2, result.size()); + assertEquals("e3", result.get(0).getEmbedded10()); + assertEquals("ex3", result.get(1).getEmbedded10()); + } + } + @Test public void queryWithBatchIterator() throws Exception { createSelectDataSet2();
