I use the following to view large tables where fetching the all the results is not feasible. It has about 1 million rows.
It does assume that you object implements the interface Idable shown next. | | import java.io.IOException; | import java.io.Serializable; | import java.util.ArrayList; | import java.util.HashMap; | import java.util.List; | import java.util.Map; | | import javax.faces.context.FacesContext; | | import org.ajax4jsf.model.DataVisitor; | import org.ajax4jsf.model.ExtendedDataModel; | import org.ajax4jsf.model.Range; | import org.ajax4jsf.model.SequenceRange; | import org.jboss.seam.ScopeType; | import org.jboss.seam.annotations.Logger; | import org.jboss.seam.annotations.Out; | import org.jboss.seam.log.Log; | | import my.package.Idable; | | public abstract class BaseExtendedDataModel<T,ID extends Serializable> extends ExtendedDataModel implements BaseExtendedDataModelDAO<T, ID>{ | | private @Logger Log log; | | @Out(scope=ScopeType.CONVERSATION, required=false) | public List<T> listRow; | | private ID currentId; | private Map<ID, T> wrappedData = new HashMap<ID, T>(); | private List<ID> wrappedKeys; | private Long rowCount; // better to buffer row count locally | | public abstract Long getCount(); | public abstract List<T> getList(Integer firstRow, Integer maxResults); | public abstract T findById(ID id); | | public void wrap(FacesContext context, DataVisitor visitor, Range range, Object argument, List<T> list) throws IOException | { | wrappedKeys = new ArrayList<ID>(); | wrappedData = new HashMap<ID, T>(); | for (T row : list) | { | Idable idable = (Idable) row; | ID id = (ID) idable.getId(); | wrappedKeys.add(id); | wrappedData.put(id, row); | visitor.process(context, id, argument); | } | } | | public boolean hasById(ID id) | { | for (T row : listRow) | { | Idable idable = (Idable) row; | Long rowId = (Long) idable.getId(); | if (rowId.equals(id)) | { | return true; | } | } | return false; | } | | @Override | public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException | { | int firstRow = ((SequenceRange) range).getFirstRow(); | int maxResults = ((SequenceRange) range).getRows(); | wrap(context, visitor, range, argument, getList(firstRow, maxResults)); | } | | /* | * This method normally called by Visitor before request Data Row. | */ | @Override | public void setRowKey(Object key) | { | this.currentId = (ID) key; | } | | @Override | public int getRowCount() | { | if(rowCount == null) | return (rowCount = this.getCount()).intValue(); | else | return rowCount.intValue(); | } | | @Override | public boolean isRowAvailable() | { | if (currentId == null) { | return false; | } else { | return hasById(currentId); | } | } | | /** | * This is main way to obtain data row. It is intensively used by framework. | * We strongly recommend use of local cache in that method. | */ | @Override | public Object getRowData() { | if (currentId == null) { | return null; | } else { | T ret = wrappedData.get(currentId); | if (ret == null) { | ret = this.findById(currentId); | wrappedData.put(currentId, ret); | return ret; | } else { | return ret; | } | } | } | | /** | * Unused rudiment from old JSF staff. | */ | @Override public Object getWrappedData() { throw new UnsupportedOperationException(); } | @Override public int getRowIndex() { throw new UnsupportedOperationException(); } | @Override public void setRowIndex(int rowIndex) { throw new UnsupportedOperationException(); } | @Override public void setWrappedData(Object data) { throw new UnsupportedOperationException(); } | | /** | * Unused update data. | */ | // @Override public void update() { throw new UnsupportedOperationException(); } | | /** | * TODO if this is never called by the framework why is it necessary. | */ | @Override public Object getRowKey() { if (true) throw new UnsupportedOperationException(); return currentId; } | | } | | public interface BaseExtendedDataModelDAO<T, ID> { | | | | } | | Idable interface | public interface Idable | { | public Long getId(); | } | I extend the base class as shown below. | import java.util.List; | | import org.jboss.seam.annotations.In; | import org.jboss.seam.annotations.Name; | | import mypackage.general.access.Access; | | @Name("accessExtendedDataModel") | public class AccessExtendedDataModel extends BaseExtendedDataModel<Access, Long> | { | @In(create=true) AccessDAO accessDAO; | | @Override | public Long getCount() | { | return accessDAO.getCount(); | } | | @Override | public Access findById(Long id) | { | return accessDAO.findById(id); | } | | @Override | public List<Access> getList(Integer firstRow, Integer maxResults) | { | return listRow = accessDAO.getRange(firstRow, maxResults); | } | Then in the facelets page | <a4j:form> | <rich:datascroller for="accessList" /> | <rich:spacer height="10" /> | <rich:dataTable id="accessList" | value="#{accessExtendedDataModel}" | var="accessL" | styleClass="f_table" | rowClasses="tr0,tr1" | rows="30"> | <rich:column id="id"> | <f:facet name="header">id</f:facet> | <h:outputText value="#{accessL.id}" /> | </rich:column> | <rich:column id="User"> | <f:facet name="header">User</f:facet> | <h:outputText value="#{accessL.usr.usr}" /> | </rich:column> | </rich:dataTable> | </a4j:form> | The scroller is now connected to the datatable. This is a first pass and was adapted for an example in the Richfaces cvs I took a while back. The paging is all done with Ajax and only 30 objects are loaded at a time. Any suggestions for improvement are most welcome. View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4112998#4112998 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4112998 _______________________________________________ jboss-user mailing list jboss-user@lists.jboss.org https://lists.jboss.org/mailman/listinfo/jboss-user