RichFaces ExtendedTableDataModel:排序列检索所有行

时间:2010-09-14 10:08:12

标签: sorting jsf datatable richfaces

我们使用ExtendedTableDataModel进行分页。这样做是为了使用Hibernate检索一组结果,并在请求另一个页面时加载下一组。

一切正常,但是如果我们在rich:dataTable中使用rich:column sortBy对列进行排序,那么RichFaces会尝试加载所有行。我们可以在调试我们为自定义DataProvider制作的getItemsByRange时看到这一点。单击排序一次后,RichFaces将继续从数据库中检索所有行。这当然不是我们想要的。我们希望使用此解决方案来最小化数据流量和加载时间。

我们使用Richfaces 3.3.2。是否有人有可能的解决方案或解决方法?

1 个答案:

答案 0 :(得分:4)

我们遇到了同样的问题,这是我们的解决方案。我不完全确定我粘贴的整个代码是相关的,但它应该是

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();
    }
}

您还需要自定义DataProvider

public class PagingDataProvider implements DataProvider<BeanDisplay>,
      Sortable2, Filterable 

在方法getItemsByRange中,使查询仅加载有限数量的记录。所有其他方法应该直接实现(我没有粘贴我们的代码,因为它充满了非常具体的代码,这是不相关的)

您可以按如下方式构建数据模型:

new PagingExtendedTableDataModel<BeanDisplay>(new PagingDataProvider());