Skip to content

Commit 9bda4cd

Browse files
author
Igor Polevoy
committed
#401 Add dynamic flag to Paginator
1 parent 0a01b8c commit 9bda4cd

File tree

2 files changed

+96
-58
lines changed

2 files changed

+96
-58
lines changed

activejdbc/src/main/java/org/javalite/activejdbc/Paginator.java

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
/*
22
Copyright 2009-2014 Igor Polevoy
33
4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
10-
Unless required by applicable law or agreed to in writing, software
11-
distributed under the License is distributed on an "AS IS" BASIS,
12-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
See the License for the specific language governing permissions and
14-
limitations under the License.
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
1515
*/
1616

1717

@@ -45,41 +45,52 @@ public class Paginator<T extends Model> implements Serializable {
4545
private int currentPage;
4646
private final boolean fullQuery;
4747
private final String countQuery;
48+
private boolean suppressCounts = false;
49+
private Long count = 0L;
4850

4951

52+
/**
53+
* Convenience constructor. Calls {@link #Paginator(Class, int, String, Object...)} and passes true for <code>suppressCounts</code>.
54+
*/
55+
public Paginator(Class<? extends T> modelClass, int pageSize, String query, Object... params) {
56+
this(modelClass, pageSize, false, query, params);
57+
}
58+
5059
/**
5160
* Paginator is created with parameters to jump to chunks of result sets (pages). This class is useful "paging"
5261
* through result on a user interface (web page).
53-
*
62+
* <p/>
5463
* <h4>Examples of a sub-query:</h4>
5564
* <ul>
56-
* <li><code>"last_name like '%John%'"</code> - this is a sub-query, and the rest of the information will be filled out
65+
* <li><code>"last_name like '%John%'"</code> - this is a sub-query, and the rest of the information will be filled out
5766
* by this class</li>
58-
* <li> "*" - will search for all records, no filtering</li>
67+
* <li> "*" - will search for all records, no filtering</li>
5968
* </ul>
6069
* Sub-query is used in simple cases, when filtering is done against one table.
61-
*
70+
* <p/>
6271
* <h4>Full query example</h4>
6372
* <ul>
64-
* <li>"select * from people where last_name like '%John%'"</li>
73+
* <li>"select * from people where last_name like '%John%'"</li>
6574
* </ul>
6675
* Full query is used in cases when select covers many tables. In this case, the selected columns need to include
6776
* attributes of the model class.
6877
*
69-
* @param modelClass model class mapped to a table.
70-
* @param pageSize number of items per page.
71-
* @param params a set of parameters if a query is parametrized (has question marks '?').
72-
* @param query this is a query that will be applied every time a new page is requested; this
73-
* query should not contain limit, offset or order by clauses of any kind, Paginator will do this automatically.
74-
* This parameter can have two forms, a sub-query or a full query.
75-
*
76-
*
78+
* @param modelClass model class mapped to a table.
79+
* @param pageSize number of items per page.
80+
* @param suppressCounts suppress calling "select count(*)... " on a table each time. If set to true,
81+
* it will call count only once. If set to false, it will call count each time
82+
* {@link #getCount()} is called from {@link #hasNext()} as well.
83+
* @param params a set of parameters if a query is parametrized (has question marks '?').
84+
* @param query this is a query that will be applied every time a new page is requested; this
85+
* query should not contain limit, offset or order by clauses of any kind, Paginator will do this automatically.
86+
* This parameter can have two forms, a sub-query or a full query.
7787
*/
78-
public Paginator(Class<? extends T> modelClass, int pageSize, String query, Object... params) {
88+
public Paginator(Class<? extends T> modelClass, int pageSize, boolean suppressCounts, String query, Object... params) {
7989

80-
try{
90+
this.suppressCounts = suppressCounts;
91+
try {
8192
Class.forName(modelClass.getName());
82-
}catch(ClassNotFoundException e){
93+
} catch (ClassNotFoundException e) {
8394
throw new InitException(e);
8495
}
8596

@@ -99,7 +110,7 @@ public Paginator(Class<? extends T> modelClass, int pageSize, String query, Obje
99110
} else if (query.equals("*")) {
100111
if (params.length == 0) {
101112
this.countQuery = metaModel.getDialect().selectCount(tableName);
102-
} else{
113+
} else {
103114
throw new IllegalArgumentException("cannot provide parameters with query: '*'");
104115
}
105116
} else {
@@ -122,7 +133,7 @@ public Paginator orderBy(String orderBys) {
122133
* This method will return a list of records for a specific page.
123134
*
124135
* @param pageNumber page number to return. This is indexed at 1, not 0. Any value below 1 is illegal and will
125-
* be rejected.
136+
* be rejected.
126137
* @return list of records that match a query make up a "page".
127138
*/
128139
public LazyList<T> getPage(int pageNumber) {
@@ -146,35 +157,36 @@ public LazyList<T> getPage(int pageNumber) {
146157
*
147158
* @return index of current page, or 0 if this instance has not produced a page yet.
148159
*/
149-
public int getCurrentPage(){
160+
public int getCurrentPage() {
150161
return currentPage;
151162
}
152163

153164
/**
154165
* Synonym for {@link #hasPrevious()}.
155166
*
156-
* @return true if a previous page is available.
167+
* @return true if a previous page is available.
157168
*/
158-
public boolean getPrevious(){
169+
public boolean getPrevious() {
159170
return hasPrevious();
160171
}
161-
public boolean hasPrevious(){
172+
173+
public boolean hasPrevious() {
162174
return currentPage > 1 && currentPage <= pageCount();
163175
}
164176

165177
/**
166178
* Synonym for {@link #hasNext()}.
167-
*
168-
* @return true if a next page is available.
179+
*
180+
* @return true if a next page is available.
169181
*/
170-
public boolean getNext(){
182+
public boolean getNext() {
171183
return hasNext();
172184
}
173185

174-
public boolean hasNext(){
186+
public boolean hasNext() {
175187
return currentPage < pageCount();
176188
}
177-
189+
178190
public long pageCount() {
179191
try {
180192
long results = getCount();
@@ -189,12 +201,12 @@ private LazyList<T> find(String query, Object... params) {
189201
if (query.equals("*")) {
190202
if (params.length == 0) {
191203
return findAll();
192-
} else{
204+
} else {
193205
throw new IllegalArgumentException("cannot provide parameters with query: '*'");
194206
}
195207
}
196-
return fullQuery ? new LazyList<T>(true, metaModel, this.query, params)
197-
: new LazyList<T>(query, metaModel, params);
208+
return fullQuery ? new LazyList<T>(true, metaModel, this.query, params)
209+
: new LazyList<T>(query, metaModel, params);
198210
}
199211

200212
private LazyList<T> findAll() {
@@ -207,20 +219,24 @@ private LazyList<T> findAll() {
207219
* @return total count of records based on provided criteria
208220
*/
209221
public Long getCount() {
210-
Long result = null;
211-
if (metaModel.cached()) {
212-
result = (Long) QueryCache.instance().getItem(metaModel.getTableName(), countQuery, params);
213-
if (result == null) {
214-
result = doCount();
215-
QueryCache.instance().addItem(metaModel.getTableName(), countQuery, params, result);
222+
if (count == 0L || !suppressCounts) {
223+
if (metaModel.cached()) {
224+
count = (Long) QueryCache.instance().getItem(metaModel.getTableName(), countQuery, params);
225+
if (count == null || count == 0) {
226+
count = doCount();
227+
QueryCache.instance().addItem(metaModel.getTableName(), countQuery, params, count);
228+
}
229+
} else {
230+
count = doCount();
216231
}
232+
return count;
233+
217234
} else {
218-
result = doCount();
235+
return count;
219236
}
220-
return result;
221237
}
222238

223-
private Long doCount(){
239+
private Long doCount() {
224240
return Convert.toLong(new DB(metaModel.getDbName()).firstCell(countQuery, params));
225241
}
226242
}

activejdbc/src/test/java/org/javalite/activejdbc/PaginatorTest.java

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
/*
22
Copyright 2009-2014 Igor Polevoy
33
4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
10-
Unless required by applicable law or agreed to in writing, software
11-
distributed under the License is distributed on an "AS IS" BASIS,
12-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
See the License for the specific language governing permissions and
14-
limitations under the License.
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
1515
*/
1616

1717

@@ -46,7 +46,7 @@ public void testCurrentPage(){
4646
p.getPage(1);
4747
a(p.getCurrentPage()).shouldBeEqual(1);
4848
}
49-
49+
5050
@Test
5151
public void testPageCount(){
5252
Paginator<Item> p = new Paginator<Item>(Item.class, 10, "item_description like '%2%'");
@@ -134,4 +134,26 @@ public void shouldPaginateWithRawSql(){
134134
a(items.get(0).get("item_number")).shouldBeEqual(992);
135135
a(p.pageCount()).shouldBeEqual(28);
136136
}
137+
138+
@Test
139+
public void should_ignore_changes_in_count_after_started(){
140+
Paginator<Item> p = new Paginator<Item>(Item.class, 10, true, "*");
141+
a(p.getCount()).shouldBeEqual(1000);
142+
//lets add more records
143+
for(int i = 1; i <= 4; i++){
144+
Item.createIt("item_number", i, "item_description", "this is item # " + i);
145+
}
146+
a(p.getCount()).shouldBeEqual(1000);
147+
}
148+
149+
@Test
150+
public void should_not_ignore_changes_in_count_after_started(){
151+
Paginator<Item> p = new Paginator<Item>(Item.class, 10, "*");
152+
a(p.getCount()).shouldBeEqual(1000);
153+
//lets add more records
154+
for(int i = 1; i <= 4; i++){
155+
Item.createIt("item_number", i, "item_description", "this is item # " + i);
156+
}
157+
a(p.getCount()).shouldBeEqual(1004);
158+
}
137159
}

0 commit comments

Comments
 (0)