Blog信息 |
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7585768 建立时间:2006年5月29日 |

| |
[软件设计]Pageable DisplayTag with Hibernate 软件技术
lhwork 发表于 2007/1/23 12:09:49 |
啊~~~~~~ 昨、今兩天都跟 DisplayTag 大戰。搞了好久總算搞定了。DisplayTag 這個 taglib 寫的真很不錯,介面很好看,而且 pageable, sort, group 使用上都很簡單。最後還有無限變化的 decorator,設計的人真的非常有經驗!然而它還是有一些地方還不夠完美。使用它的 page 功能,比方說120筆分12頁,每頁10筆好了,它沒有機制可以讓你一次只讀10筆。一定要一次讀完 120 筆才行。這樣分頁的用意就少了一大半了!這兩天就都花在這玩意上,浪費了好多時間。最後的答案還算差強人意。HibernatePageList page = new HibernatePageList(pageSize, "from Foo f where f.id >20" ) ;page.loadPage(2) ;HibernatePageList 是一個帶有 iterator() method 的 list (不全是,沒有 implement List) 。這個物件裡面會有空的 list,裡面全部裝滿 null,整個 list 的大小就是 上面 "from... >20" query 出來的筆數。當執行 loadPage(2) 時,內部會去抽第二頁所需的資料,然後 HibernatePageList這個物件的內部的List 的第二頁會被填滿(其餘保持 null) 。如此當使用者點到分頁的第二頁時,在 servlet/action 裡執行 loadPage(2),就可以讀取需要顯示的值。displayTag 本身並沒有提供讀取目前是第幾個分頁的功能。我們只好從它的 request parameter 下手;當 displayTag 分頁時,比如說第三頁,它會在 url 後面接上 "&d-12345-p=3" 這樣的 parameter 。12345 是它產生的隨機碼,有時是四個數字。抓取這個數字可用 regular expression : params.match("d-[0-9]+-p") 這個 pattern 來找,找到後便可傳給 loadPage. 所以最後可簡化為:page.loadPage(request) ; // get current pageNo from request完整的程式碼如下:public class HibernatePageList {private List cachedList;private int pageNo;private int pageSize;private int totalSize;private String queryString;public HibernatePageList(int pageSize, int totalSize, String queryString) {this.queryString = queryString;this.pageSize = pageSize;this.totalSize = totalSize;// initialize full list with null;cachedList = new ArrayList(totalSize);for (int i = 0; i < totalSize; i++) {cachedList.add(null);}}public HibernatePageList(int pageSize, String fromBasedQueryString)throws HibernateException {this(pageSize,getTotalSize(fromBasedQueryString),fromBasedQueryString);}private static int getTotalSize(String fromBasedQueryString)throws HibernateException {return ((Integer) HibernateUtil.currentSession().iterate("select count(*) " + fromBasedQueryString).next()).intValue();}public void loadPage(final int pageNo) throws HibernateException {//check cache has data:if (pageIsCached(pageNo)) {return;}Query query = HibernateUtil.currentSession().createQuery(queryString);query.setMaxResults(pageSize);query.setFirstResult(getPageStartRow(pageNo));final Iterator iter = query.iterate();for (int i = getPageStartRow(pageNo); iter.hasNext(); i++) {cachedList.set(i, iter.next());}}public void loadPage(HttpServletRequest request)throws HibernateException {loadPage(getDisplayTagPageNo(request));}/*** extract page no from request of display tag* * @param request* @return* @throws NumberFormatException*/public int getDisplayTagPageNo(HttpServletRequest request)throws NumberFormatException {Enumeration names = request.getParameterNames();int pageNo = 1;while (names.hasMoreElements()) {String parameter = (String) names.nextElement();if (parameter.matches("d-[0-9]+-p")) {pageNo = Integer.parseInt(request.getParameter(parameter));break;}}return pageNo;}private int getPageEndRow(int pageNo) {return Math.min(pageNo * pageSize, totalSize);}private int getPageStartRow(int pageNo) {return (pageNo - 1) * pageSize;}private boolean pageIsCached(final int pageNo) {boolean pageIsCached = true;for (int i = getPageStartRow(pageNo);i < getPageEndRow(pageNo) && pageIsCached;i++) {if (cachedList.get(i) == null) {pageIsCached = false;}}return pageIsCached;}public Object get(int index) {return cachedList.get(index);}public boolean isEmpty() {return cachedList.isEmpty();}public Iterator iterator() {return cachedList.iterator();}public int size() {return cachedList.size();}public int getPageSize() {return pageSize;}public String getQueryString() {return queryString;}} |
|
|