001package com.avaje.ebean; 002 003import java.util.List; 004import java.util.concurrent.Future; 005 006/** 007 * Represents a page of results. 008 * <p> 009 * The benefit of using PagedList over just using the normal Query with 010 * {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} is that it additionally wraps 011 * functionality that can call {@link Query#findFutureRowCount()} to determine total row count, 012 * total page count etc. 013 * </p> 014 * <p> 015 * Internally this works using {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} on 016 * the query. This translates into SQL that uses limit offset, rownum or row_number function to 017 * limit the result set. 018 * </p> 019 * 020 * <h4>Example: typical use including total row count</h4> 021 * <pre>{@code 022 * 023 * // We want to find the first 100 new orders 024 * // ... 0 means first page 025 * // ... page size is 100 026 * 027 * PagedList<Order> pagedList 028 * = ebeanServer.find(Order.class) 029 * .where().eq("status", Order.Status.NEW) 030 * .order().asc("id") 031 * .findPagedList(0, 100); 032 * 033 * // Optional: initiate the loading of the total 034 * // row count in a background thread 035 * pagedList.loadRowCount(); 036 * 037 * // fetch and return the list in the foreground thread 038 * List<Order> orders = pagedList.getList(); 039 * 040 * // get the total row count (from the future) 041 * int totalRowCount = pagedList.getTotalRowCount(); 042 * 043 * }</pre> 044 * 045 * <h4>Example: No total row count required</h4> 046 * <pre>{@code 047 * 048 * // If you are not getting the 'first page' often 049 * // you do not bother getting the total row count again 050 * // so instead just get the page list of data 051 * 052 * // fetch and return the list in the foreground thread 053 * List<Order> orders = pagedList.getList(); 054 * 055 * }</pre> 056 * 057 * @param <T> 058 * the entity bean type 059 * 060 * @see Query#findPagedList(int, int) 061 */ 062public interface PagedList<T> { 063 064 /** 065 * Initiate the loading of the total row count in the background. 066 * <pre>{@code 067 * 068 * // initiate the loading of the total row count 069 * // in a background thread 070 * pagedList.loadRowCount(); 071 * 072 * // fetch and return the list in the foreground thread 073 * List<Order> orders = pagedList.getList(); 074 * 075 * // get the total row count (from the future) 076 * int totalRowCount = pagedList.getTotalRowCount(); 077 * 078 * }</pre> 079 * 080 * <p> 081 * Also note that using loadRowCount() and getTotalRowCount() rather than getFutureRowCount() 082 * means that exceptions ExecutionException, InterruptedException, TimeoutException are instead 083 * wrapped in the unchecked PersistenceException (which might be preferrable). 084 * </p> 085 */ 086 void loadRowCount(); 087 088 /** 089 * Return the Future row count. You might get this if you wish to cancel the total row count query 090 * or specify a timeout for the row count query. 091 * <p> 092 * The loadRowCount() & getTotalRowCount() methods internally make use of this getFutureRowCount() method. 093 * Generally I expect people to prefer loadRowCount() & getTotalRowCount() over getFutureRowCount(). 094 * </p> 095 * <pre>{@code 096 * 097 * // initiate the row count query in the background thread 098 * Future<Integer> rowCount = pagedList.getFutureRowCount(); 099 * 100 * // fetch and return the list in the foreground thread 101 * List<Order> orders = pagedList.getList(); 102 * 103 * // now get the total count with a timeout 104 * Integer totalRowCount = rowCount.get(30, TimeUnit.SECONDS); 105 * 106 * // or ge the total count without a timeout 107 * Integer totalRowCountViaFuture = rowCount.get(); 108 * 109 * // which is actually the same as ... 110 * int totalRowCount = pagedList.getTotalRowCount(); 111 * 112 * }</pre> 113 */ 114 Future<Integer> getFutureRowCount(); 115 116 /** 117 * Return the list of entities for this page. 118 */ 119 List<T> getList(); 120 121 /** 122 * Return the total row count for all pages. 123 * <p> 124 * If loadRowCount() has already been called then the row count query is already executing in a background thread 125 * and this gets the associated Future and gets the value waiting for the future to finish. 126 * </p> 127 * <p> 128 * If loadRowCount() has not been called then this executes the find row count query and returns the result and this 129 * will just occur in the current thread and not use a background thread. 130 * </p> 131 * <pre>{@code 132 * 133 * // Optional: initiate the loading of the total 134 * // row count in a background thread 135 * pagedList.loadRowCount(); 136 * 137 * // fetch and return the list in the foreground thread 138 * List<Order> orders = pagedList.getList(); 139 * 140 * // get the total row count (which was being executed 141 * // in a background thread if loadRowCount() was used) 142 * int totalRowCount = pagedList.getTotalRowCount(); 143 * 144 * }</pre> 145 */ 146 int getTotalRowCount(); 147 148 /** 149 * Return the total number of pages based on the page size and total row count. 150 * <p> 151 * This method requires that the total row count has been fetched and will invoke 152 * the total row count query if it has not already been invoked. 153 * </p> 154 */ 155 int getTotalPageCount(); 156 157 /** 158 * Return the index position of this page. Zero based. 159 */ 160 int getPageIndex(); 161 162 /** 163 * Return the page size used for this query. 164 */ 165 int getPageSize(); 166 167 /** 168 * Return true if there is a next page. 169 * <p> 170 * This method requires that the total row count has been fetched and will invoke 171 * the total row count query if it has not already been invoked. 172 * </p> 173 */ 174 boolean hasNext(); 175 176 /** 177 * Return true if there is a previous page. 178 */ 179 boolean hasPrev(); 180 181 /** 182 * Helper method to return a "X to Y of Z" string for this page where X is the first row, Y the 183 * last row and Z the total row count. 184 * <p> 185 * This method requires that the total row count has been fetched and will invoke 186 * the total row count query if it has not already been invoked. 187 * </p> 188 * 189 * @param to 190 * String to put between the first and last row 191 * @param of 192 * String to put between the last row and the total row count 193 * 194 * @return String of the format XtoYofZ. 195 */ 196 String getDisplayXtoYofZ(String to, String of); 197}