-
-
Notifications
You must be signed in to change notification settings - Fork 261
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#3462 Add Paging as alternative to maxRows + firstRow + orderBy
Paging is an alternative to specifying the maxRows + firstRow + orderBy on a query. Example: ```java var orderBy = OrderBy.of("lastName desc nulls first, firstName asc"); var paging = Paging.of(0, 100, orderBy); DB.find(Contact.class) .setPaging(paging) .where().startsWith("lastName", "foo") .findList(); ```
- Loading branch information
Showing
8 changed files
with
291 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package io.ebean; | ||
|
||
final class DPaging implements Paging { | ||
|
||
static final Paging NONE = new DPaging(0, 0, null); | ||
|
||
static Paging build(int pgIndex, int pgSize, OrderBy<?> orderBy) { | ||
return new DPaging(pgIndex, pgSize, orderBy); | ||
} | ||
|
||
static Paging build(int pgIndex, int pgSize) { | ||
return new DPaging(pgIndex, pgSize, null); | ||
} | ||
|
||
private final int pageNumber; | ||
private final int pageSize; | ||
private final OrderBy<?> orderBy; | ||
|
||
DPaging(int pageNumber, int pageSize, OrderBy<?> orderBy) { | ||
this.pageNumber = pageNumber; | ||
this.pageSize = pageSize; | ||
this.orderBy = orderBy; | ||
} | ||
|
||
@Override | ||
public int pageIndex() { | ||
return pageNumber; | ||
} | ||
|
||
@Override | ||
public int pageSize() { | ||
return pageSize; | ||
} | ||
|
||
@Override | ||
public OrderBy<?> orderBy() { | ||
return orderBy; | ||
} | ||
|
||
@Override | ||
public Paging withPage(int pageNumber) { | ||
return new DPaging(pageNumber, pageSize, orderBy); | ||
} | ||
|
||
@Override | ||
public Paging withOrderBy(String orderByClause) { | ||
return new DPaging(pageNumber, pageSize, OrderBy.of(orderByClause)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package io.ebean; | ||
|
||
import io.avaje.lang.Nullable; | ||
|
||
/** | ||
* Used to specify Paging on a Query as an alternative to setting each of the | ||
* maxRows, firstRow and orderBy clause via: | ||
* {@link Query#setMaxRows(int)} + {@link Query#setFirstRow(int)} + {@link Query#setOrderBy(OrderBy)}. | ||
* <p> | ||
* Example use: | ||
* | ||
* <pre>{@code | ||
* | ||
* var orderBy = OrderBy.of("lastName desc nulls first, firstName asc"); | ||
* var paging = Paging.of(0, 100, orderBy); | ||
* | ||
* DB.find(Contact.class) | ||
* .setPaging(paging) | ||
* .where().startsWith("lastName", "foo") | ||
* .findList(); | ||
* | ||
* }</pre> | ||
*/ | ||
public interface Paging { | ||
|
||
/** | ||
* Create a Paging with the given page index size and orderBy. | ||
* | ||
* @param pageIndex the page index starting from zero | ||
* @param pageSize the page size (effectively max rows) | ||
* @param orderBy order by for the query result | ||
*/ | ||
static Paging of(int pageIndex, int pageSize, @Nullable OrderBy<?> orderBy) { | ||
return DPaging.build(pageIndex, pageSize, orderBy); | ||
} | ||
|
||
/** | ||
* Create a Paging with a raw order by clause. | ||
* | ||
* @param pageIndex the page index starting from zero | ||
* @param pageSize the page size (effectively max rows) | ||
* @param orderByClause raw order by clause for ordering the query result | ||
*/ | ||
static Paging of(int pageIndex, int pageSize, @Nullable String orderByClause) { | ||
return of(pageIndex, pageSize, OrderBy.of(orderByClause)); | ||
} | ||
|
||
/** | ||
* Create a Paging that will use the id property for ordering. | ||
* | ||
* @param pageIndex the page index starting from zero | ||
* @param pageSize the page size (effectively max rows) | ||
*/ | ||
static Paging of(int pageIndex, int pageSize) { | ||
return DPaging.build(pageIndex, pageSize); | ||
} | ||
|
||
/** | ||
* Return a Paging that will not apply any pagination to a query. | ||
*/ | ||
static Paging ofNone() { | ||
return DPaging.NONE; | ||
} | ||
|
||
/** | ||
* Return the page index. | ||
*/ | ||
int pageIndex(); | ||
|
||
/** | ||
* Return the page size. | ||
*/ | ||
int pageSize(); | ||
|
||
/** | ||
* Return the order by. | ||
*/ | ||
OrderBy<?> orderBy(); | ||
|
||
/** | ||
* Return a Paging using the given page index. | ||
*/ | ||
Paging withPage(int pageIndex); | ||
|
||
/** | ||
* Return a Paging using the given order by clause. | ||
*/ | ||
Paging withOrderBy(String orderByClause); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
ebean-test/src/test/java/org/tests/query/TestQueryPaging.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package org.tests.query; | ||
|
||
import io.ebean.DB; | ||
import io.ebean.OrderBy; | ||
import io.ebean.Paging; | ||
import io.ebean.test.LoggedSql; | ||
import io.ebean.xtest.BaseTestCase; | ||
import org.junit.jupiter.api.Test; | ||
import org.tests.model.basic.Contact; | ||
import org.tests.model.basic.ResetBasicData; | ||
|
||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
class TestQueryPaging extends BaseTestCase { | ||
|
||
@Test | ||
void example() { | ||
var orderBy = OrderBy.of("lastName desc nulls first, firstName asc"); | ||
var paging = Paging.of(0, 100, orderBy); | ||
|
||
DB.find(Contact.class) | ||
.setPaging(paging) | ||
.where().startsWith("lastName", "foo") | ||
.findList(); | ||
// or instead of findList() use another find method like ... | ||
// findPagedList(), findEach(), findStream(), findMap(), findSet(), findSingleAttributeList(), | ||
|
||
var nextPage = paging.withPage(1); | ||
|
||
DB.find(Contact.class) | ||
.setPaging(nextPage) | ||
.findList(); | ||
} | ||
|
||
@Test | ||
void whenNoOrderBy_expect_orderByIdUsed() { | ||
ResetBasicData.reset(); | ||
|
||
LoggedSql.start(); | ||
|
||
DB.find(Contact.class).select("lastName").setPaging(Paging.of(0, 4)).findList(); | ||
DB.find(Contact.class).select("lastName").setPaging(Paging.of(2, 4)).findList(); | ||
|
||
List<String> sql = LoggedSql.stop(); | ||
assertThat(sql).hasSize(2); | ||
if (isLimitOffset()) { | ||
assertThat(sql.get(0)).contains("order by t0.id limit 4"); | ||
assertThat(sql.get(1)).contains("order by t0.id limit 4 offset 8"); | ||
} | ||
} | ||
|
||
@Test | ||
void whenOrderBy_expect_noExtraIdInTheOrderBy() { | ||
ResetBasicData.reset(); | ||
|
||
LoggedSql.start(); | ||
|
||
DB.find(Contact.class).select("lastName").setPaging(Paging.of(1, 4, "lastName")).findList(); | ||
DB.find(Contact.class).select("lastName").setPaging(Paging.of(1, 4, "lastName, id")).findList(); | ||
|
||
List<String> sql = LoggedSql.stop(); | ||
assertThat(sql).hasSize(2); | ||
if (isLimitOffset()) { | ||
assertThat(sql.get(0)).contains("order by t0.last_name limit 4 offset 4"); | ||
assertThat(sql.get(1)).contains("order by t0.last_name, t0.id limit 4 offset 4"); | ||
} | ||
} | ||
|
||
@Test | ||
void whenNone_expect_noLimitOffsetAtAll() { | ||
ResetBasicData.reset(); | ||
|
||
LoggedSql.start(); | ||
|
||
DB.find(Contact.class).select("lastName").setPaging(Paging.ofNone()).findList(); | ||
|
||
List<String> sql = LoggedSql.stop(); | ||
assertThat(sql).hasSize(1); | ||
assertThat(sql.get(0)).contains("select t0.id, t0.last_name from contact t0;"); | ||
} | ||
|
||
@Test | ||
void withPage() { | ||
Paging paging = Paging.of(0, 100); | ||
assertThat(paging.pageIndex()).isEqualTo(0); | ||
assertThat(paging.pageSize()).isEqualTo(100); | ||
|
||
Paging pg1 = paging.withPage(1); | ||
assertThat(pg1.pageIndex()).isEqualTo(1); | ||
assertThat(pg1.pageSize()).isEqualTo(100); | ||
|
||
Paging pg6 = paging.withPage(6); | ||
assertThat(pg6.pageIndex()).isEqualTo(6); | ||
assertThat(pg6.pageSize()).isEqualTo(100); | ||
} | ||
|
||
@Test | ||
void withOrderBy() { | ||
Paging pg1 = Paging.of(1, 100); | ||
assertThat(pg1.pageIndex()).isEqualTo(1); | ||
assertThat(pg1.pageSize()).isEqualTo(100); | ||
|
||
Paging pgWithOrder = pg1.withOrderBy("lastName desc nulls first, firstName asc"); | ||
OrderBy<?> orderBy = pgWithOrder.orderBy(); | ||
List<OrderBy.Property> properties = orderBy.getProperties(); | ||
assertThat(properties).hasSize(2); | ||
assertThat(properties.get(0).getProperty()).isEqualTo("lastName"); | ||
assertThat(properties.get(0).isAscending()).isFalse(); | ||
assertThat(properties.get(1).getProperty()).isEqualTo("firstName"); | ||
assertThat(properties.get(1).isAscending()).isTrue(); | ||
} | ||
} |