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 * 021 * <h4>Example: typical use including total row count</h4> 022 * <pre>{@code 023 * 024 * // We want to find the first 50 new orders 025 * // ... so we don't really need setFirstRow(0) 026 * 027 * PagedList<Order> pagedList 028 * = ebeanServer.find(Order.class) 029 * .where().eq("status", Order.Status.NEW) 030 * .order().asc("id") 031 * .setFirstRow(0) 032 * .setMaxRows(50) 033 * .findPagedList(); 034 * 035 * // Optional: initiate the loading of the total 036 * // row count in a background thread 037 * pagedList.loadRowCount(); 038 * 039 * // fetch and return the list in the foreground thread 040 * List<Order> orders = pagedList.getList(); 041 * 042 * // get the total row count (from the future) 043 * int totalRowCount = pagedList.getTotalRowCount(); 044 * 045 * }</pre> 046 * 047 * <h4>Example: typical use including total row count</h4> 048 * <pre>{@code 049 * 050 * // We want to find the first 100 new orders 051 * // ... 0 means first page 052 * // ... page size is 100 053 * 054 * PagedList<Order> pagedList 055 * = ebeanServer.find(Order.class) 056 * .where().eq("status", Order.Status.NEW) 057 * .order().asc("id") 058 * .findPagedList(0, 100); 059 * 060 * // Optional: initiate the loading of the total 061 * // row count in a background thread 062 * pagedList.loadRowCount(); 063 * 064 * // fetch and return the list in the foreground thread 065 * List<Order> orders = pagedList.getList(); 066 * 067 * // get the total row count (from the future) 068 * int totalRowCount = pagedList.getTotalRowCount(); 069 * 070 * }</pre> 071 * 072 * <h4>Example: No total row count required</h4> 073 * <pre>{@code 074 * 075 * // If you are not getting the 'first page' often 076 * // you do not bother getting the total row count again 077 * // so instead just get the page list of data 078 * 079 * // fetch and return the list in the foreground thread 080 * List<Order> orders = pagedList.getList(); 081 * 082 * }</pre> 083 * 084 * @param <T> 085 * the entity bean type 086 * 087 * @see Query#findPagedList() 088 */ 089public interface PagedList<T> { 090 091 /** 092 * Initiate the loading of the total row count in the background. 093 * <pre>{@code 094 * 095 * // initiate the loading of the total row count 096 * // in a background thread 097 * pagedList.loadRowCount(); 098 * 099 * // fetch and return the list in the foreground thread 100 * List<Order> orders = pagedList.getList(); 101 * 102 * // get the total row count (from the future) 103 * int totalRowCount = pagedList.getTotalRowCount(); 104 * 105 * }</pre> 106 * 107 * <p> 108 * Also note that using loadRowCount() and getTotalRowCount() rather than getFutureRowCount() 109 * means that exceptions ExecutionException, InterruptedException, TimeoutException are instead 110 * wrapped in the unchecked PersistenceException (which might be preferrable). 111 * </p> 112 */ 113 void loadCount(); 114 115 /** 116 * Deprecated in favor of loadCount(). 117 * 118 * @deprecated 119 */ 120 void loadRowCount(); 121 122 /** 123 * Return the Future row count. You might get this if you wish to cancel the total row count query 124 * or specify a timeout for the row count query. 125 * <p> 126 * The loadRowCount() & getTotalRowCount() methods internally make use of this getFutureRowCount() method. 127 * Generally I expect people to prefer loadRowCount() & getTotalRowCount() over getFutureRowCount(). 128 * </p> 129 * <pre>{@code 130 * 131 * // initiate the row count query in the background thread 132 * Future<Integer> rowCount = pagedList.getFutureRowCount(); 133 * 134 * // fetch and return the list in the foreground thread 135 * List<Order> orders = pagedList.getList(); 136 * 137 * // now get the total count with a timeout 138 * Integer totalRowCount = rowCount.get(30, TimeUnit.SECONDS); 139 * 140 * // or ge the total count without a timeout 141 * Integer totalRowCountViaFuture = rowCount.get(); 142 * 143 * // which is actually the same as ... 144 * int totalRowCount = pagedList.getTotalRowCount(); 145 * 146 * }</pre> 147 */ 148 Future<Integer> getFutureCount(); 149 150 /** 151 * Deprecated in favor of getFutureCount(). 152 * 153 * @deprecated 154 */ 155 Future<Integer> getFutureRowCount(); 156 157 /** 158 * Return the list of entities for this page. 159 */ 160 List<T> getList(); 161 162 /** 163 * Return the total row count for all pages. 164 * <p> 165 * If loadRowCount() has already been called then the row count query is already executing in a background thread 166 * and this gets the associated Future and gets the value waiting for the future to finish. 167 * </p> 168 * <p> 169 * If loadRowCount() has not been called then this executes the find row count query and returns the result and this 170 * will just occur in the current thread and not use a background thread. 171 * </p> 172 * <pre>{@code 173 * 174 * // Optional: initiate the loading of the total 175 * // row count in a background thread 176 * pagedList.loadRowCount(); 177 * 178 * // fetch and return the list in the foreground thread 179 * List<Order> orders = pagedList.getList(); 180 * 181 * // get the total row count (which was being executed 182 * // in a background thread if loadRowCount() was used) 183 * int totalRowCount = pagedList.getTotalRowCount(); 184 * 185 * }</pre> 186 */ 187 int getTotalCount(); 188 189 /** 190 * Deprecated in favor of getTotalCount(). 191 * 192 * @deprecated 193 */ 194 int getTotalRowCount(); 195 196 /** 197 * Return the total number of pages based on the page size and total row count. 198 * <p> 199 * This method requires that the total row count has been fetched and will invoke 200 * the total row count query if it has not already been invoked. 201 * </p> 202 */ 203 int getTotalPageCount(); 204 205 /** 206 * Return the page size used for this query. This is the same value as maxRows used by the query. 207 */ 208 int getPageSize(); 209 210 /** 211 * Return true if there is a next page. 212 * <p> 213 * This method requires that the total row count has been fetched and will invoke 214 * the total row count query if it has not already been invoked. 215 * </p> 216 */ 217 boolean hasNext(); 218 219 /** 220 * Return true if there is a previous page. 221 */ 222 boolean hasPrev(); 223 224 /** 225 * Helper method to return a "X to Y of Z" string for this page where X is the first row, Y the 226 * last row and Z the total row count. 227 * <p> 228 * This method requires that the total row count has been fetched and will invoke 229 * the total row count query if it has not already been invoked. 230 * </p> 231 * 232 * @param to 233 * String to put between the first and last row 234 * @param of 235 * String to put between the last row and the total row count 236 * 237 * @return String of the format XtoYofZ. 238 */ 239 String getDisplayXtoYofZ(String to, String of); 240}