package io.ebean;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.concurrent.Future;

Represents a page of results.

The benefit of using PagedList over just using the normal Query with Query.setFirstRow(int) and Query.setMaxRows(int) is that it additionally wraps functionality that can call Query.findFutureCount() to determine total row count, total page count etc.

Internally this works using Query.setFirstRow(int) and Query.setMaxRows(int) on the query. This translates into SQL that uses limit offset, rownum or row_number function to limit the result set.

Example: typical use including total row count


    // We want to find the first 50 new orders
    //  ... so we don't really need setFirstRow(0)
    PagedList<Order> pagedList = DB.find(Order.class)
      .where().eq("status", Order.Status.NEW)
      .order().asc("id")
      .setFirstRow(0)
      .setMaxRows(50)
      .findPagedList();
    // Optional: initiate the loading of the total
    // row count in a background thread
    pagedList.loadRowCount();
    // fetch and return the list in the foreground thread
    List<Order> orders = pagedList.getList();
    // get the total row count (from the future)
    int totalRowCount = pagedList.getTotalRowCount();

Example: No total row count required


    // If you are not getting the 'first page' often
    // you do not bother getting the total row count again
    // so instead just get the page list of data
    // fetch and return the list in the foreground thread
    List<Order> orders = pagedList.getList();
Type parameters:
  • <T> – the entity bean type
See Also:
/** * Represents a page of results. * <p> * The benefit of using PagedList over just using the normal Query with * {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} is that it additionally wraps * functionality that can call {@link Query#findFutureCount()} to determine total row count, * total page count etc. * </p> * <p> * Internally this works using {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} on * the query. This translates into SQL that uses limit offset, rownum or row_number function to * limit the result set. * </p> * <p> * <h4>Example: typical use including total row count</h4> * <pre>{@code * * // We want to find the first 50 new orders * // ... so we don't really need setFirstRow(0) * * PagedList<Order> pagedList = DB.find(Order.class) * .where().eq("status", Order.Status.NEW) * .order().asc("id") * .setFirstRow(0) * .setMaxRows(50) * .findPagedList(); * * // Optional: initiate the loading of the total * // row count in a background thread * pagedList.loadRowCount(); * * // fetch and return the list in the foreground thread * List<Order> orders = pagedList.getList(); * * // get the total row count (from the future) * int totalRowCount = pagedList.getTotalRowCount(); * * }</pre> * <p> * <h4>Example: No total row count required</h4> * <pre>{@code * * // If you are not getting the 'first page' often * // you do not bother getting the total row count again * // so instead just get the page list of data * * // fetch and return the list in the foreground thread * List<Order> orders = pagedList.getList(); * * }</pre> * * @param <T> the entity bean type * @see Query#findPagedList() */
public interface PagedList<T> {
Initiate the loading of the total row count in the background.

    // initiate the loading of the total row count
    // in a background thread
    pagedList.loadRowCount();
    // fetch and return the list in the foreground thread
    List<Order> orders = pagedList.getList();
    // get the total row count (from the future)
    int totalRowCount = pagedList.getTotalRowCount();

Also note that using loadRowCount() and getTotalRowCount() rather than getFutureRowCount() means that exceptions ExecutionException, InterruptedException, TimeoutException are instead wrapped in the unchecked PersistenceException (which might be preferrable).

/** * Initiate the loading of the total row count in the background. * <pre>{@code * * // initiate the loading of the total row count * // in a background thread * pagedList.loadRowCount(); * * // fetch and return the list in the foreground thread * List<Order> orders = pagedList.getList(); * * // get the total row count (from the future) * int totalRowCount = pagedList.getTotalRowCount(); * * }</pre> * <p> * Also note that using loadRowCount() and getTotalRowCount() rather than getFutureRowCount() * means that exceptions ExecutionException, InterruptedException, TimeoutException are instead * wrapped in the unchecked PersistenceException (which might be preferrable). * </p> */
void loadCount();
Return the Future row count. You might get this if you wish to cancel the total row count query or specify a timeout for the row count query.

The loadRowCount() & getTotalRowCount() methods internally make use of this getFutureRowCount() method. Generally I expect people to prefer loadRowCount() & getTotalRowCount() over getFutureRowCount().


    // initiate the row count query in the background thread
    Future<Integer> rowCount = pagedList.getFutureRowCount();
    // fetch and return the list in the foreground thread
    List<Order> orders = pagedList.getList();
    // now get the total count with a timeout
    Integer totalRowCount = rowCount.get(30, TimeUnit.SECONDS);
    // or ge the total count without a timeout
    Integer totalRowCountViaFuture = rowCount.get();
    // which is actually the same as ...
    int totalRowCount = pagedList.getTotalRowCount();
/** * Return the Future row count. You might get this if you wish to cancel the total row count query * or specify a timeout for the row count query. * <p> * The loadRowCount() & getTotalRowCount() methods internally make use of this getFutureRowCount() method. * Generally I expect people to prefer loadRowCount() & getTotalRowCount() over getFutureRowCount(). * </p> * <pre>{@code * * // initiate the row count query in the background thread * Future<Integer> rowCount = pagedList.getFutureRowCount(); * * // fetch and return the list in the foreground thread * List<Order> orders = pagedList.getList(); * * // now get the total count with a timeout * Integer totalRowCount = rowCount.get(30, TimeUnit.SECONDS); * * // or ge the total count without a timeout * Integer totalRowCountViaFuture = rowCount.get(); * * // which is actually the same as ... * int totalRowCount = pagedList.getTotalRowCount(); * * }</pre> */
@Nonnull Future<Integer> getFutureCount();
Return the list of entities for this page.
/** * Return the list of entities for this page. */
@Nonnull List<T> getList();
Return the total row count for all pages.

If loadRowCount() has already been called then the row count query is already executing in a background thread and this gets the associated Future and gets the value waiting for the future to finish.

If loadRowCount() has not been called then this executes the find row count query and returns the result and this will just occur in the current thread and not use a background thread.


    // Optional: initiate the loading of the total
    // row count in a background thread
    pagedList.loadRowCount();
    // fetch and return the list in the foreground thread
    List<Order> orders = pagedList.getList();
    // get the total row count (which was being executed
    // in a background thread if loadRowCount() was used)
    int totalRowCount = pagedList.getTotalRowCount();
/** * Return the total row count for all pages. * <p> * If loadRowCount() has already been called then the row count query is already executing in a background thread * and this gets the associated Future and gets the value waiting for the future to finish. * </p> * <p> * If loadRowCount() has not been called then this executes the find row count query and returns the result and this * will just occur in the current thread and not use a background thread. * </p> * <pre>{@code * * // Optional: initiate the loading of the total * // row count in a background thread * pagedList.loadRowCount(); * * // fetch and return the list in the foreground thread * List<Order> orders = pagedList.getList(); * * // get the total row count (which was being executed * // in a background thread if loadRowCount() was used) * int totalRowCount = pagedList.getTotalRowCount(); * * }</pre> */
int getTotalCount();
Return the total number of pages based on the page size and total row count.

This method requires that the total row count has been fetched and will invoke the total row count query if it has not already been invoked.

/** * Return the total number of pages based on the page size and total row count. * <p> * This method requires that the total row count has been fetched and will invoke * the total row count query if it has not already been invoked. * </p> */
int getTotalPageCount();
Return the page size used for this query. This is the same value as maxRows used by the query.
/** * Return the page size used for this query. This is the same value as maxRows used by the query. */
int getPageSize();
Return the index position of this page (Zero based).

This is a calculated value based on firstRow/maxRows.

/** * Return the index position of this page (Zero based). * <p> * This is a calculated value based on firstRow/maxRows. * </p> */
int getPageIndex();
Return true if there is a next page.

This method requires that the total row count has been fetched and will invoke the total row count query if it has not already been invoked.

/** * Return true if there is a next page. * <p> * This method requires that the total row count has been fetched and will invoke * the total row count query if it has not already been invoked. * </p> */
boolean hasNext();
Return true if there is a previous page.
/** * Return true if there is a previous page. */
boolean hasPrev();
Helper method to return a "X to Y of Z" string for this page where X is the first row, Y the last row and Z the total row count.

This method requires that the total row count has been fetched and will invoke the total row count query if it has not already been invoked.

Params:
  • to – String to put between the first and last row
  • of – String to put between the last row and the total row count
Returns:String of the format XtoYofZ.
/** * Helper method to return a "X to Y of Z" string for this page where X is the first row, Y the * last row and Z the total row count. * <p> * This method requires that the total row count has been fetched and will invoke * the total row count query if it has not already been invoked. * </p> * * @param to String to put between the first and last row * @param of String to put between the last row and the total row count * @return String of the format XtoYofZ. */
String getDisplayXtoYofZ(String to, String of); }