We had the same problem, and here's our solution. I'm not entirely sure that the whole code I'm pasting is relevant, but it should be
public class PagingExtendedTableDataModel<T> extends ExtendedDataModel implements
Serializable, Modifiable {
private DataProvider dataProvider;
private Object rowKey;
private List wrappedKeys;
private Map wrappedData;
private Integer rowCount;
private Integer rowIndex;
private List<FilterField> filterFields;
private List<SortField2> sortFields;
public PagingExtendedTableDataModel(DataProvider<T> dataProvider) {
wrappedKeys = null;
wrappedData = new HashMap();
rowCount = null;
rowIndex = Integer.valueOf(-1);
rowKey = null;
this.dataProvider = dataProvider;
}
public Object getRowKey() {
return rowKey;
}
public void setRowKey(Object key) {
rowKey = key;
}
@SuppressWarnings("unchecked")
public void walk(FacesContext context, DataVisitor visitor, Range range,
Object argument) throws IOException {
int rowC = getRowCount();
int firstRow = ((SequenceRange) range).getFirstRow();
int numberOfRows = ((SequenceRange) range).getRows();
if (numberOfRows <= 0) {
numberOfRows = rowC;
}
if (wrappedKeys != null) {
Object key;
for (Iterator it = wrappedKeys.iterator(); it.hasNext();
visitor.process(context, key, argument)) {
key = it.next();
setRowKey(key);
}
} else {
wrappedKeys = new ArrayList();
int endRow = firstRow + numberOfRows;
if (endRow > rowC) {
endRow = rowC;
}
if (dataProvider instanceof Sortable2) {
((Sortable2) dataProvider).setSortFields(sortFields);
}
if (dataProvider instanceof Filterable) {
((Filterable) dataProvider).setFilterFields(filterFields);
}
Object key;
for (Iterator it = loadData(firstRow, endRow).iterator(); it.hasNext();
visitor.process(context, key, argument)) {
Object item = it.next();
key = getKey(item);
wrappedKeys.add(key);
wrappedData.put(key, item);
}
}
}
protected List loadData(int startRow, int endRow) {
if (startRow < 0) {
startRow = 0;
throw new IllegalArgumentException((new StringBuilder()).append(
"Illegal start index value: ").append(startRow).toString());
}
int rowCount = getRowCount();
if (endRow > rowCount) {
endRow = rowCount;
throw new IllegalArgumentException((new StringBuilder()).append(
"Illegal end index value: ").append(endRow).toString());
}
return dataProvider.getItemsByRange(startRow, endRow);
}
public int getRowCount() {
if (rowCount == null) {
rowCount = new Integer(dataProvider.getRowCount());
} else {
return rowCount.intValue();
}
return rowCount.intValue();
}
public Object getRowData() {
if (rowKey == null) {
return null;
}
return getObjectByKey(rowKey);
}
@SuppressWarnings("unchecked")
public Object getKey(Object o) {
return dataProvider.getKey(o);
}
@SuppressWarnings("unchecked")
public Object getObjectByKey(Object key) {
Object t = wrappedData.get(key);
if (t == null) {
t = dataProvider.getItemByKey(key);
wrappedData.put(key, t);
}
return t;
}
public int getRowIndex() {
return rowIndex.intValue();
}
public void setRowIndex(int rowIndex) {
this.rowIndex = Integer.valueOf(rowIndex);
}
public Object getWrappedData() {
throw new UnsupportedOperationException();
}
public void setWrappedData(Object data) {
throw new UnsupportedOperationException();
}
public boolean isRowAvailable() {
return getRowData() != null;
}
public void reset() {
wrappedKeys = null;
wrappedData.clear();
rowCount = null;
rowIndex = Integer.valueOf(-1);
rowKey = null;
}
public DataProvider getDataProvider() {
return dataProvider;
}
public void setDataProvider(DataProvider dataProvider) {
this.dataProvider = dataProvider;
}
@Override
public void modify(List<FilterField> filterFields, List<SortField2> sortFields) {
this.filterFields = filterFields;
this.sortFields = sortFields;
reset();
}
}
And you also need a custom DataProvider
public class PagingDataProvider implements DataProvider<BeanDisplay>,
Sortable2, Filterable
In the method getItemsByRange
make your query load only a limited amount of records. All other methods should be straightforward to implement (I'm not pasting our code, because it is full of quite specific code, which is not relevant)
And you construct your data model as follows:
new PagingExtendedTableDataModel<BeanDisplay>(new PagingDataProvider());