rich:dataScroller 似乎仍然加载所有数据而不分页
rich:dataScroller seems to still load all the data without pagination
我正在尝试为一个从数据库加载大量数据的项目实现分页。
我已经在 Internet 上进行了大量搜索以使 db-pagination 正常工作,但出于某种原因我仍然无法按我想要的方式工作。
我已经按照本主题中描述的示例进行操作:
JSF, RichFaces, pagination
数据已加载,可以正常工作;缓存似乎也有效。但是,它似乎仍然加载所有数据。 walk-method 中的 sr.getRows()
总是 -1
,因此对数据库的调用也使用 -1 来表示 maxResults
。我得到了所有数据,但没有分页。
如果可以避免,我不想引入另一个依赖项。
我的一些数据:
BatchDataModel
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> {
private SequenceRange cachedRange;
private Integer cachedRowCount;
private List<T> cachedList;
private Object rowKey;
public abstract List<T> getDataList(int firstRow, int numRows);
public abstract Object getKey(T t);
public abstract int getTotalCount();
@Override
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument) {
SequenceRange sr = (SequenceRange) range;
if (cachedList == null || !equalRanges(cachedRange, sr)) {
cachedList = getDataList(sr.getFirstRow(), sr.getRows());
cachedRange = sr;
}
for (T t : cachedList) {
if (getKey(t) == null) {
/*
* the 2nd param is used to build the client id of the table
* row, i.e. mytable:234:inputname, so don't let it be null.
*/
throw new IllegalStateException("found null key");
}
dv.process(ctx, getKey(t), argument);
}
}
/*
* The rowKey is the id from getKey, presumably obtained from
* dv.process(...).
*/
@Override
public void setRowKey(Object rowKey) {
this.rowKey = rowKey;
}
@Override
public Object getRowKey() {
return rowKey;
}
@Override
public boolean isRowAvailable() {
return (getRowData() != null);
}
@Override
public int getRowCount() {
if (cachedRowCount == null) {
cachedRowCount = getTotalCount();
}
return cachedRowCount;
}
@Override
public T getRowData() {
for (T t : cachedList) {
if (getKey(t).equals(this.getRowKey())) {
return t;
}
}
return null;
}
protected static boolean equalRanges(SequenceRange range1, SequenceRange range2) {
if (range1 == null || range2 == null) {
return range1 == null && range2 == null;
} else {
return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows();
}
}
/*
* get/setRowIndex are used when doing multiple select in an
* extendedDataTable, apparently. Not tested. Actually, the get method is
* used when using iterationStatusVar="it" & #{it.index}.
*/
@Override
public int getRowIndex() {
if (cachedList != null) {
ListIterator<T> it = cachedList.listIterator();
while (it.hasNext()) {
T t = it.next();
if (getKey(t).equals(this.getRowKey())) {
return it.previousIndex() + cachedRange.getFirstRow();
}
}
}
return -1;
}
@Override
public void setRowIndex(int rowIndex) {
int upperBound = cachedRange.getFirstRow() + cachedRange.getRows();
if (rowIndex >= cachedRange.getFirstRow() && rowIndex < upperBound) {
int index = rowIndex % cachedRange.getRows();
T t = cachedList.get(index);
setRowKey(getKey(t));
}
}
@Override
public Object getWrappedData() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setWrappedData(Object data) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<T> getCachedList() {
return cachedList;
}
Bean(部分)
private ListState state;
private BatchDataModel<Batch> model;
public BatchDataModel<Batch> getModel(){
return model;
}
public int getCurrentPage() {
return state.getPage();
}
public void setCurrentPage(int page) {
state.setPage(page);
}
public void setBatchService(BatchService batchService) {
this.batchService = batchService;
}
/**
* Initialize the variables, before the page is shown.
*/
@PostConstruct
private void init() {
filter = new Filter();
sorter = new Sorter();
state = getFromSession("batchList", null);
if (state == null) {
state = new ListState();
storeInSession("batchList", state);
}
}
public void loadBatches(boolean search) {
BatchDataModel<Batch> model = new BatchDataModel<Batch>(){
@Override
public List<Batch> getDataList(int firstRow, int numRows) {
try {
List <Batch> test;
test = batchService.selectBatches(userBean.getUser(), firstRow, numRows);
return test;
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return null;
}
}
@Override
public Object getKey(Batch batch) {
return batch.getBatchId();
}
@Override
public int getTotalCount() {
try {
return batchService.countBatches(userBean.getUser());
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return 0;
}
}
};
}
xhtml(部分)
<rich:dataTable id="batchesTable" rows="2"
value="#{batchBean.model}" var="batch" first="#{batchBean.currentPage}"
styleClass="table" rowClasses="odd-row, even-row"
onrowmouseover="this.style.backgroundColor='#88B5F9'"
onrowmouseout="this.style.backgroundColor='#{a4jSkin.rowBackgroundColor}'">
(...)
<f:facet name="footer">
<rich:dataScroller page="#{batchBean.currentPage}" />
</f:facet>
ArrangeableModel 是关键。这个 class 需要在 BatchDataModel class 中与方法和函数一起实现。这样使用相同的状态 walk-method
在 SequenceRange
.
中得到正确的值
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> implements Arrangeable {
private ArrangeableState arrangeableState;
public void arrange(FacesContext context, ArrangeableState state) {
arrangeableState = state;
}
protected ArrangeableState getArrangeableState() {
return arrangeableState;
}
}
我正在尝试为一个从数据库加载大量数据的项目实现分页。 我已经在 Internet 上进行了大量搜索以使 db-pagination 正常工作,但出于某种原因我仍然无法按我想要的方式工作。
我已经按照本主题中描述的示例进行操作: JSF, RichFaces, pagination
数据已加载,可以正常工作;缓存似乎也有效。但是,它似乎仍然加载所有数据。 walk-method 中的 sr.getRows()
总是 -1
,因此对数据库的调用也使用 -1 来表示 maxResults
。我得到了所有数据,但没有分页。
如果可以避免,我不想引入另一个依赖项。
我的一些数据:
BatchDataModel
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> {
private SequenceRange cachedRange;
private Integer cachedRowCount;
private List<T> cachedList;
private Object rowKey;
public abstract List<T> getDataList(int firstRow, int numRows);
public abstract Object getKey(T t);
public abstract int getTotalCount();
@Override
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument) {
SequenceRange sr = (SequenceRange) range;
if (cachedList == null || !equalRanges(cachedRange, sr)) {
cachedList = getDataList(sr.getFirstRow(), sr.getRows());
cachedRange = sr;
}
for (T t : cachedList) {
if (getKey(t) == null) {
/*
* the 2nd param is used to build the client id of the table
* row, i.e. mytable:234:inputname, so don't let it be null.
*/
throw new IllegalStateException("found null key");
}
dv.process(ctx, getKey(t), argument);
}
}
/*
* The rowKey is the id from getKey, presumably obtained from
* dv.process(...).
*/
@Override
public void setRowKey(Object rowKey) {
this.rowKey = rowKey;
}
@Override
public Object getRowKey() {
return rowKey;
}
@Override
public boolean isRowAvailable() {
return (getRowData() != null);
}
@Override
public int getRowCount() {
if (cachedRowCount == null) {
cachedRowCount = getTotalCount();
}
return cachedRowCount;
}
@Override
public T getRowData() {
for (T t : cachedList) {
if (getKey(t).equals(this.getRowKey())) {
return t;
}
}
return null;
}
protected static boolean equalRanges(SequenceRange range1, SequenceRange range2) {
if (range1 == null || range2 == null) {
return range1 == null && range2 == null;
} else {
return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows();
}
}
/*
* get/setRowIndex are used when doing multiple select in an
* extendedDataTable, apparently. Not tested. Actually, the get method is
* used when using iterationStatusVar="it" & #{it.index}.
*/
@Override
public int getRowIndex() {
if (cachedList != null) {
ListIterator<T> it = cachedList.listIterator();
while (it.hasNext()) {
T t = it.next();
if (getKey(t).equals(this.getRowKey())) {
return it.previousIndex() + cachedRange.getFirstRow();
}
}
}
return -1;
}
@Override
public void setRowIndex(int rowIndex) {
int upperBound = cachedRange.getFirstRow() + cachedRange.getRows();
if (rowIndex >= cachedRange.getFirstRow() && rowIndex < upperBound) {
int index = rowIndex % cachedRange.getRows();
T t = cachedList.get(index);
setRowKey(getKey(t));
}
}
@Override
public Object getWrappedData() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setWrappedData(Object data) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<T> getCachedList() {
return cachedList;
}
Bean(部分)
private ListState state;
private BatchDataModel<Batch> model;
public BatchDataModel<Batch> getModel(){
return model;
}
public int getCurrentPage() {
return state.getPage();
}
public void setCurrentPage(int page) {
state.setPage(page);
}
public void setBatchService(BatchService batchService) {
this.batchService = batchService;
}
/**
* Initialize the variables, before the page is shown.
*/
@PostConstruct
private void init() {
filter = new Filter();
sorter = new Sorter();
state = getFromSession("batchList", null);
if (state == null) {
state = new ListState();
storeInSession("batchList", state);
}
}
public void loadBatches(boolean search) {
BatchDataModel<Batch> model = new BatchDataModel<Batch>(){
@Override
public List<Batch> getDataList(int firstRow, int numRows) {
try {
List <Batch> test;
test = batchService.selectBatches(userBean.getUser(), firstRow, numRows);
return test;
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return null;
}
}
@Override
public Object getKey(Batch batch) {
return batch.getBatchId();
}
@Override
public int getTotalCount() {
try {
return batchService.countBatches(userBean.getUser());
} catch (NozemException e) {
LOGGER.error(e.getMessage());
sendMessage(e.getMessage(), true);
return 0;
}
}
};
}
xhtml(部分)
<rich:dataTable id="batchesTable" rows="2"
value="#{batchBean.model}" var="batch" first="#{batchBean.currentPage}"
styleClass="table" rowClasses="odd-row, even-row"
onrowmouseover="this.style.backgroundColor='#88B5F9'"
onrowmouseout="this.style.backgroundColor='#{a4jSkin.rowBackgroundColor}'">
(...)
<f:facet name="footer">
<rich:dataScroller page="#{batchBean.currentPage}" />
</f:facet>
ArrangeableModel 是关键。这个 class 需要在 BatchDataModel class 中与方法和函数一起实现。这样使用相同的状态 walk-method
在 SequenceRange
.
public abstract class BatchDataModel<T> extends ExtendedDataModel<T> implements Arrangeable {
private ArrangeableState arrangeableState;
public void arrange(FacesContext context, ArrangeableState state) {
arrangeableState = state;
}
protected ArrangeableState getArrangeableState() {
return arrangeableState;
}
}