mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Add PagedList was part of #96
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.junit.Test;
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Update;
|
||||
import com.avaje.tests.model.basic.EBasic;
|
||||
|
||||
public class TestExplicitInsert extends BaseTestCase {
|
||||
@@ -16,9 +15,6 @@ public class TestExplicitInsert extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
// GlobalProperties.put("ebean.classes",
|
||||
// ""+LDPerson.class.toString()+","+EBasic.class.toString());
|
||||
|
||||
EBasic b = new EBasic();
|
||||
b.setName("exp insert");
|
||||
b.setDescription("explicit insert");
|
||||
@@ -38,28 +34,9 @@ public class TestExplicitInsert extends BaseTestCase {
|
||||
Assert.assertNotNull(b2.getId());
|
||||
Assert.assertTrue(!b.getId().equals(b2.getId()));
|
||||
|
||||
List<EBasic> list = server.find(EBasic.class).setMaxRows(10).findList();
|
||||
List<EBasic> list = server.find(EBasic.class).where().in("id",b.getId(), b2.getId()).findList();
|
||||
|
||||
Assert.assertTrue(list.size() >= 2);
|
||||
|
||||
int firstRow = 1;
|
||||
List<EBasic> list2 = server.find(EBasic.class).order().asc("id").setFirstRow(firstRow)
|
||||
.setMaxRows(10).findList();
|
||||
|
||||
int expectedCount = list.size() - firstRow;
|
||||
if (expectedCount > 0) {
|
||||
Assert.assertEquals(expectedCount, list2.size());
|
||||
} else {
|
||||
Assert.assertTrue(list2.isEmpty());
|
||||
}
|
||||
|
||||
Update<EBasic> update = Ebean.createUpdate(EBasic.class,
|
||||
"update ebasic set description = 'test'");
|
||||
|
||||
int rows = update.execute();
|
||||
|
||||
Assert.assertTrue(rows > 0);
|
||||
Ebean.externalModification("e_basic", true, false, true);
|
||||
Assert.assertEquals(2, list.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.avaje.tests.query.other;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.PagedList;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.tests.model.basic.EBasic;
|
||||
|
||||
public class TestFindPagedList extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() throws InterruptedException, ExecutionException {
|
||||
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Transaction transaction = server.beginTransaction();
|
||||
try {
|
||||
transaction.setBatchMode(true);
|
||||
transaction.setBatchSize(20);
|
||||
for (int i = 0; i < 87; i++) {
|
||||
EBasic dumbModel = new EBasic();
|
||||
dumbModel.setName("HelloB0Bi");
|
||||
server.save(dumbModel);
|
||||
}
|
||||
transaction.commit();
|
||||
|
||||
} finally {
|
||||
transaction.end();
|
||||
}
|
||||
|
||||
PagedList<EBasic> list1 = Ebean.find(EBasic.class)
|
||||
.where().like("name", "HelloB0B%")
|
||||
.findPagedList(0, 10);
|
||||
|
||||
list1.loadRowCount();
|
||||
List<EBasic> list = list1.getList();
|
||||
int totalRowCount = list1.getTotalRowCount();
|
||||
int totalPageCount = list1.getTotalPageCount();
|
||||
|
||||
Assert.assertEquals(10, list.size());
|
||||
Assert.assertEquals(87, totalRowCount);
|
||||
Assert.assertEquals(9, totalPageCount);
|
||||
|
||||
PagedList<EBasic> list2 = Ebean.find(EBasic.class)
|
||||
.where().like("name", "HelloB0B%")
|
||||
.findPagedList(4, 10);
|
||||
|
||||
list = list2.getList();
|
||||
|
||||
Assert.assertEquals(10, list2.getList().size());
|
||||
Assert.assertEquals(87, list2.getTotalRowCount());
|
||||
Assert.assertEquals(9, list2.getTotalPageCount());
|
||||
|
||||
PagedList<EBasic> list3 = Ebean.find(EBasic.class)
|
||||
.where().like("name", "HelloB0B%")
|
||||
.findPagedList(8, 10);
|
||||
|
||||
Future<Integer> rowCount = list3.getFutureRowCount();
|
||||
list = list3.getList();
|
||||
|
||||
Assert.assertEquals(Integer.valueOf(87), rowCount.get());
|
||||
Assert.assertEquals(7, list3.getList().size());
|
||||
Assert.assertEquals(87, list3.getTotalRowCount());
|
||||
Assert.assertEquals(9, list3.getTotalPageCount());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user