/** * Resolves a sublist of objects starting at <code>fromIndex</code> up to but not including <code> * toIndex</code>. Internally performs bound checking and trims indexes accordingly. */ protected void resolveInterval(int fromIndex, int toIndex) { if (fromIndex >= toIndex) { return; } synchronized (elements) { if (elements.size() == 0) { return; } // perform bound checking if (fromIndex < 0) { fromIndex = 0; } if (toIndex > elements.size()) { toIndex = elements.size(); } List<Expression> quals = new ArrayList<>(pageSize); List<Object> ids = new ArrayList<>(pageSize); for (int i = fromIndex; i < toIndex; i++) { Object object = elements.get(i); if (helper.unresolvedSuspect(object)) { quals.add(buildIdQualifier(object)); ids.add(object); } } int qualsSize = quals.size(); if (qualsSize == 0) { return; } // fetch the range of objects in fetchSize chunks boolean fetchesDataRows = internalQuery.isFetchingDataRows(); List<Object> objects = new ArrayList<>(qualsSize); int fetchSize = maxFetchSize > 0 ? maxFetchSize : Integer.MAX_VALUE; int fetchEnd = Math.min(qualsSize, fetchSize); int fetchBegin = 0; while (fetchBegin < qualsSize) { SelectQuery<Object> query = new SelectQuery<>( rootEntity, ExpressionFactory.joinExp(Expression.OR, quals.subList(fetchBegin, fetchEnd))); query.setFetchingDataRows(fetchesDataRows); if (!query.isFetchingDataRows()) { query.setPrefetchTree(internalQuery.getPrefetchTree()); } objects.addAll(dataContext.performQuery(query)); fetchBegin = fetchEnd; fetchEnd += Math.min(fetchSize, qualsSize - fetchEnd); } // sanity check - database data may have changed checkPageResultConsistency(objects, ids); // replace ids in the list with objects Iterator it = objects.iterator(); while (it.hasNext()) { helper.updateWithResolvedObjectInRange(it.next(), fromIndex, toIndex); } unfetchedObjects -= objects.size(); } }