encodedCursor = (String) cache.get(key);
}
if (encodedCursor != null) {
// Got a cursor, use it
Cursor cursor = Cursor.fromWebSafeString(encodedCursor);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
query.setFirstResult(0);
} else if (firstResult + maxResults < 1000) {
// Results may be retrieved directly using "OFFSET"
query.setHint(JPACursorHelper.CURSOR_HINT, null);
query.setFirstResult(firstResult);
} else {
// Skip results
int pos = (firstResult / 1000) * 1000;
Cursor trialCursor = null;
while (pos > 0) {
String trialKey = createKey(employeeId, department, startsWith,
orderBy, pos);
String trialEncodedCursor = (String) cache.get(trialKey);
if (trialEncodedCursor != null) {
trialCursor = Cursor.fromWebSafeString(trialEncodedCursor);
break;
}
pos -= 1000;
}
// If trialCursor is null, we'll start searching from result 0
query.setHint(JPACursorHelper.CURSOR_HINT, trialCursor);
while (firstResult > pos) {
int min = Math.min(firstResult - pos, 1000);
// If we need to skip more than 1000 records, ensure the
// breaks occur at multiples of 1000 in order to increase the
// chances of reusing cursors from the memcache
if (pos + min < firstResult) {
int mod = (pos + min) % 1000;
min -= mod;
}
query.setMaxResults(min);
List<ReportBack> results = query.getResultList();
int count = results.size();
if (count == 0) {
break;
}
pos += count;
// Save the cursor for later
Cursor cursor = JPACursorHelper.getCursor(results);
if (cache != null) {
String key = createKey(employeeId, department, startsWith, orderBy,
pos);
cache.put(key, cursor.toWebSafeString());
}
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
}
query.setMaxResults(maxResults);
List<ReportBack> reportList = query.getResultList();
// force it to materialize
reportList.size();
Cursor cursor = JPACursorHelper.getCursor(reportList);
if (cache != null) {
int pos = firstResult + reportList.size();
String key = createKey(employeeId, department, startsWith, orderBy, pos);
cache.put(key, cursor.toWebSafeString());
}
return reportList;
} finally {
em.close();