package hamaster.gradesign.jsf.page; import java.util.List; import javax.faces.model.DataModel; import javax.faces.model.DataModelEvent; import javax.faces.model.DataModelListener; /** * 完成Richfaces调用数据库分页的类 * @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a> * @param <E> 显示的类模板 */ public abstract class DatabasePageDataModel<E> extends DataModel<E> { /** * 每一页大小 */ private int pageSize; /** * cache中第一条数据相对于数据库中第一条数据的偏移量 */ private int absoluteOffset; /** * 要获取的数据相对于数据库中第一条数据的偏移量 */ private int index; /** * 内存中的一页数据 */ private List<E> cache; /** * 缓存的数据总数 */ protected volatile int count; protected long interval = 30 * 1000L; private volatile boolean running; /** * @param pageSize 每一页显示数量 */ public DatabasePageDataModel(int pageSize) { this.pageSize = pageSize; absoluteOffset = 0; index = 0; count = -1; running = true; } /* * (non-Javadoc) * @see javax.faces.model.DataModel#getRowData() */ @Override public E getRowData() { if (!isRowAvailable()) return null; if (index < absoluteOffset || index > absoluteOffset + pageSize || cache == null) { int page = index / pageSize; cache = list(page, pageSize); absoluteOffset = page * pageSize; } return cache.get(index - absoluteOffset); } /* * (non-Javadoc) * @see javax.faces.model.DataModel#isRowAvailable() */ @Override public boolean isRowAvailable() { return getRowIndex() < getRowCount() && getRowIndex() != -1 && getRowCount() != -1; } /* * (non-Javadoc) * @see javax.faces.model.DataModel#getRowCount() */ @Override public int getRowCount() { int dbCount = getCountImpl(); return dbCount > 0 ? dbCount : -1; } public int getCount() { if (count > -1) return count; count = getCountImpl(); // Richfaces会频繁调用getCountImpl方法,一个简单的缓存提高效率 Thread t = new Thread() { @Override public void run() { while (DatabasePageDataModel.this.running) { try { Thread.sleep(getInterval()); } catch (InterruptedException e) { } DatabasePageDataModel.this.count = getCount(); } } }; t.start(); return count; } /* * (non-Javadoc) * @see javax.faces.model.DataModel#getRowIndex() */ @Override public int getRowIndex() { return index; } /* * (non-Javadoc) * @see javax.faces.model.DataModel#setRowIndex(int) */ @Override public void setRowIndex(int rowIndex) { if (rowIndex < -1) { throw new IllegalArgumentException(); } int old = index; index = rowIndex; if (cache == null) { return; } DataModelListener[] listeners = getDataModelListeners(); if ((old != index) && (listeners != null)) { Object rowData = null; if (isRowAvailable()) { rowData = getRowData(); } DataModelEvent event = new DataModelEvent(this, index, rowData); int n = listeners.length; for (int i = 0; i < n; i++) { if (null != listeners[i]) { listeners[i].rowSelected(event); } } } } /* * (non-Javadoc) * @see javax.faces.model.DataModel#getWrappedData() */ @Override public Object getWrappedData() { return cache; } /* * (non-Javadoc) * @see javax.faces.model.DataModel#setWrappedData(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public void setWrappedData(Object data) { if (data == null) { cache = null; setRowIndex(-1); return; } if (data instanceof List) { cache = (List<E>) data; index = -1; setRowIndex(0); } } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getAbsoluteOffset() { return absoluteOffset; } public void setAbsoluteOffset(int absoluteOffset) { this.absoluteOffset = absoluteOffset; } public long getInterval() { return interval; } public void setInterval(long interval) { this.interval = interval; } public void stop() { this.running = false; } /* * (non-Javadoc) * @see java.lang.Object#finalize() */ protected void finalize() throws Throwable { this.running = false; super.finalize(); } /** * 分页获取数据 * @param page 页码 从0开始 * @param pageSize 每一页数量 * @return 数据列表 */ public abstract List<E> list(int page, int pageSize); /** * @return 数据库中的记录数量 */ public abstract int getCountImpl(); }