Add PagedList was part of #96

This commit is contained in:
Rob Bygrave
2014-05-16 01:41:56 +12:00
parent 1a4192b40f
commit 41f3173adf
11 changed files with 367 additions and 45 deletions
+24 -1
View File
@@ -547,10 +547,32 @@ public interface EbeanServer {
/**
* Find using a PagingList with explicit transaction and pageSize.
* @deprecated
* Deprecated in favour of findPagedList().
* @deprecated
*/
public <T> PagingList<T> findPagingList(Query<T> query, Transaction transaction, int pageSize);
/**
* Return a PagedList for this query.
* <p>
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
* {@link Query#findFutureRowCount()} 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>
*
* @param pageIndex
* The zero based index of the page.
* @param pageSize
* The number of beans to return per page.
* @return The PagedList
*/
public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction, int pageIndex, int pageSize);
/**
* Execute the query returning a set of entity beans.
* <p>
@@ -1079,4 +1101,5 @@ public interface EbeanServer {
*/
public JsonContext createJsonContext();
}
@@ -200,10 +200,34 @@ public interface ExpressionList<T> extends Serializable {
*
* @param pageSize
* the number of beans fetched per Page
*
* @deprecated
*/
public PagingList<T> findPagingList(int pageSize);
/**
* Return a PagedList for this query.
* <p>
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
* {@link Query#findFutureRowCount()} 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>
*
* @param pageIndex
* The zero based index of the page.
* @param pageSize
* The number of beans to return per page.
* @return The PagedList
*/
public PagedList<T> findPagedList(int pageIndex, int pageSize);
/**
* Add some filter predicate expressions to the many property.
*/
public ExpressionList<T> filterMany(String prop);
/**
@@ -0,0 +1,80 @@
package com.avaje.ebean;
import java.util.List;
import java.util.concurrent.Future;
/**
* 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#findFutureRowCount()} 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>
*
* @param <T>
* the entity bean type
*
* @see Query#findPagedList(int, int)
*/
public interface PagedList<T> {
/**
* Initiate the loading of the total row count in the background.
*/
public void loadRowCount();
/**
* Return the Future row count. You might get this if you wish to cancel the total row count query
* or specify a timeout for that query.
*/
public Future<Integer> getFutureRowCount();
/**
* Return the list of entities for this page.
*/
public List<T> getList();
/**
* Return the total row count for all pages.
*/
public int getTotalRowCount();
/**
* Return the total number of pages based on the page size and total row count.
*/
public int getTotalPageCount();
/**
* Return the index position of this page. Zero based.
*/
public int getPageIndex();
/**
* Return true if there is a next page.
*/
public boolean hasNext();
/**
* Return true if there is a previous page.
*/
public 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.
*
* @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.
*/
public String getDisplayXtoYofZ(String to, String of);
}
+23 -17
View File
@@ -589,9 +589,7 @@ public interface Query<T> extends Serializable {
/**
* Execute find list query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* Deprecated with a view to simplifying internals.
* </p>
*
* @return a Future object for the list result of the query
@@ -600,25 +598,33 @@ public interface Query<T> extends Serializable {
public FutureList<T> findFutureList();
/**
* Return a PagingList for this query.
* <p>
* This can be used to break up a query into multiple queries to fetch the
* data a page at a time.
* </p>
* <p>
* This typically works by using a query per page and setting
* {@link Query#setFirstRow(int)} and and {@link Query#setMaxRows(int)} on the
* query. This usually would translate into SQL that uses limit offset, rownum
* or row_number function to limit the result set.
* </p>
*
* @param pageSize
* the number of beans fetched per Page
* This is being deprecated in favour of the simplier {@link Query#findPagedList(int, int)}.
*
* @deprecated
*/
public PagingList<T> findPagingList(int pageSize);
/**
* Return a PagedList for this query.
* <p>
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
* {@link Query#findFutureRowCount()} 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>
*
* @param pageIndex
* The zero based index of the page.
* @param pageSize
* The number of beans to return per page.
* @return The PagedList
*/
public PagedList<T> findPagedList(int pageIndex, int pageSize);
/**
* Set a named bind parameter. Named parameters have a colon to prefix the
* name.
@@ -30,6 +30,7 @@ import com.avaje.ebean.Filter;
import com.avaje.ebean.FutureIds;
import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
@@ -96,6 +97,7 @@ import com.avaje.ebeaninternal.server.query.CallableQueryIds;
import com.avaje.ebeaninternal.server.query.CallableQueryList;
import com.avaje.ebeaninternal.server.query.CallableQueryRowCount;
import com.avaje.ebeaninternal.server.query.CallableSqlQueryList;
import com.avaje.ebeaninternal.server.query.LimitOffsetPagedList;
import com.avaje.ebeaninternal.server.query.LimitOffsetPagingQuery;
import com.avaje.ebeaninternal.server.query.QueryFutureIds;
import com.avaje.ebeaninternal.server.query.QueryFutureList;
@@ -1419,6 +1421,12 @@ public final class DefaultServer implements SpiEbeanServer {
return new LimitOffsetPagingQuery<T>(this, spiQuery, pageSize);
}
@Override
public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction, int pageIndex, int pageSize) {
return new LimitOffsetPagedList<T>(this, (SpiQuery<T>)query, pageIndex, pageSize);
}
public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
@@ -12,6 +12,7 @@ import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.Junction;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
@@ -229,6 +230,11 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
public PagingList<T> findPagingList(int pageSize) {
return exprList.findPagingList(pageSize);
}
@Override
public PagedList<T> findPagedList(int pageIndex, int pageSize) {
return exprList.findPagedList(pageIndex, pageSize);
}
public int findRowCount() {
return exprList.findRowCount();
@@ -0,0 +1,110 @@
package com.avaje.ebeaninternal.server.query;
import java.util.List;
import java.util.concurrent.Future;
import javax.persistence.PersistenceException;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.PagedList;
import com.avaje.ebeaninternal.api.Monitor;
import com.avaje.ebeaninternal.api.SpiQuery;
/**
* PagedList implementation based on limit offset types of queries.
*
* @param <T>
* the entity bean type
*/
public class LimitOffsetPagedList<T> implements PagedList<T> {
private final transient EbeanServer server;
private final SpiQuery<T> query;
private final int pageSize;
private final int pageIndex;
private final Monitor monitor = new Monitor();
private Future<Integer> futureRowCount;
private List<T> list;
public LimitOffsetPagedList(EbeanServer server, SpiQuery<T> query, int pageIndex, int pageSize) {
this.server = server;
this.query = query;
this.pageSize = pageSize;
this.pageIndex = pageIndex;
}
public void loadRowCount() {
getFutureRowCount();
}
public Future<Integer> getFutureRowCount() {
synchronized (monitor) {
if (futureRowCount == null) {
futureRowCount = server.findFutureRowCount(query, null);
}
return futureRowCount;
}
}
public List<T> getList() {
synchronized (monitor) {
if (list == null) {
query.setFirstRow(pageIndex * pageSize);
query.setMaxRows(pageSize);
list = server.findList(query, null);
}
return list;
}
}
public int getTotalPageCount() {
int rowCount = getTotalRowCount();
if (rowCount == 0) {
return 0;
} else {
return ((rowCount - 1) / pageSize) + 1;
}
}
public int getTotalRowCount() {
try {
return getFutureRowCount().get();
} catch (Exception e) {
throw new PersistenceException(e);
}
}
public boolean hasNext() {
return pageIndex < (getTotalPageCount() - 1);
}
public boolean hasPrev() {
return pageIndex > 0;
}
public int getPageIndex() {
return pageIndex;
}
public int getPageSize() {
return pageSize;
}
public String getDisplayXtoYofZ(String to, String of) {
int first = pageIndex * pageSize + 1;
int last = first + getList().size() - 1;
int total = getTotalRowCount();
return first + to + last + of + total;
}
}
@@ -18,6 +18,7 @@ import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.OrderBy.Property;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
@@ -915,7 +916,12 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
return server.findPagingList(this, null, pageSize);
}
/**
@Override
public PagedList<T> findPagedList(int pageIndex, int pageSize) {
return server.findPagedList(this, null, pageIndex, pageSize);
}
/**
* Set an ordered bind parameter according to its position. Note that the
* position starts at 1 to be consistent with JDBC PreparedStatement. You
* need to set a parameter value for each ? you have in the query.
@@ -14,6 +14,7 @@ import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.Junction;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
@@ -152,6 +153,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.findPagingList(pageSize);
}
@Override
public PagedList<T> findPagedList(int pageIndex, int pageSize) {
return query.findPagedList(pageIndex, pageSize);
}
public int findRowCount() {
return query.findRowCount();
}