<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jhonney的專欄

       ----人見人愛
    隨筆 - 49, 文章 - 1, 評論 - 23, 引用 - 0
    數據加載中……

    Limit指南

    quto:http://m.tkk7.com/lucky/archive/2006/02/23/32059.html

    1. 引言

    在你需要處理大量數據時你應該考慮使用eXtremeTable的Limit特性。Limit這個名字來自MySQL的limit 命令,Limit接口的目的就是如何對表的結果集進行limit處理。Limit實現知道當排序、過濾、分頁、導出時,用戶如何與表互相作用。有了這些信息你 將能夠使用可能是最有效的方式顯示正確的過濾、排序后的請求頁面。

    為了示范Limit特性,我將要做的工作將分解為JSP、Controller、Service和DAO。這示范了一種使用分層的方式來處理 Limit。你可以根據自己的需要來增加或減少層。本示例也使用了Spring框架來重新得到使用Spring的JDBC取得的數據,因此你的代碼看起來可能有點不同。eXtremeTable的一個特點就是不依賴任何框架和容器。

    1.1. JSP

    為了使用Limit特性,eXtremeTable需要使用limit特定的RetrieveRowsCallback、 FilterRowsCallback和SortRowsCallback接口。eXtremeComponents提供了每個接口的一個實現,可以簡單地通過設置每個屬性值為limit來簡單來使用。

    <ec:table 
    items="presidents"
    retrieveRowsCallback="limit"
    filterRowsCallback="limit"
    sortRowsCallback="limit"
    view="limit"
    >
    ...

    另外視圖屬性參照一個名為limit的定制視圖。這是一個簡單修改默認eXtremeTable視圖,不包含最后頁工具條的實現。這僅僅關系到你是否能取得確切需要的行。 一些數據庫例如Oracle和MySQL都提供了一種得到確定行的特性,但是,其他的數據庫例如:Sybase沒有提供特性。在我的示例中我考慮最壞的情況你的數據庫不支持這種特性。

    即使你的數據庫不提供取得特定行的特性,當你考慮用戶如何和表協同工作時,Limit仍然非常有意義。用戶通常會對一些數據進行排序、過濾和分頁。 這個例子中15條數據構成一頁,第一頁需要15條數據,第二頁需要30條數據,第三頁需要45條數據,以此類推。在經過一段時間分頁后,他們常常使用過濾來提煉數據。 即使他們不這樣做,他們也必須在此之前對大量的數據進行分頁,這將影響效率。當然如果允許用戶點擊最后頁,那么所有的數據都將被取出,這將非常影響效率。

    1.2. Controller

    提示:Spring框架的Controller和Struts框架的Action非常相像。

    controller首先需要創建一個Limit。為了完成這個你需要得到一些關于Context和LimitFactory的幫助。

    Context context = new HttpServletRequestContext(request);
    LimitFactory limitFactory = new TableLimitFactory(context);
    Limit limit = new TableLimit(limitFactory);

    Context是一個處理取得屬性的接口,LimitFactory使用Context來找出用戶如何和eXtremeTable交互。 然后Limit使用LimitFactory來組裝自己。

    為了初始化Limit,它將包含所有的有用的信息。這些信息包括數據將被如何排序和過濾,哪一頁將被顯示和是否允許被導出。

    然而,Limit仍然需要得到行的信息,這樣正確的信息頁面才能被顯示給用戶。行信息包括開始行、結束行、當前顯示行。 controller必須從service得到這些信息,而Service將從dao中得到這些信息。這里我只給出Controller端的代碼。

    int totalRows = presidentsService.getTotalPresidents(limit.getFilterSet(), limit.isExported());
    limit.setRowAttributes(totalRows, defaultRowsDisplayed);

    limit需要得到所有的行來得到行的信息。service需要知道那些被過濾,不管這些數據是否要導出。為了設置行信息,默認的一頁顯示的行數需要被設置。 這可以通過對TableTag的rowsDisplayed屬性設置一個確定的數值來實現。

    現在我們只需要從services得到Collection數據。

    Collection presidents = presidentsService.getPresidents(limit.getFilterSet(), limit.getSort(), limit.getRowEnd());

    因為limit已經包含所有信息,這將十分容易。所有需要做的就是傳入過濾器,排序和最后行的信息。 最后要做的是將Collections和totalRow這些信息傳送回JSP以便eXtremeTable知道如何顯示這些信息。

    request.setAttribute("presidents", presidents);
    request.setAttribute("totalRows", new Integer(totalRows));

    1.3. Service

    service需要和dao進行交互來得到總行數和Collection。

    1.3.1. 取得總行數

    controller需要到第一條信息就是總行數。

    public int getTotalPresidents(FilterSet filterSet, boolean isExported) {
    String totalQuery = presidentsDao.getTotalPresidentsQuery();
    String modTotalQuery = filterQuery(filterSet, totalQuery);
    int totalRows = presidentsDao.getTotalPresidents(modTotalQuery);
    if (isExported && totalRows > maxExportRows) {
    totalRows = maxExportRows;
    }
    return totalRows;
    }

    service和dao一起來過濾結果集,它的工作方式是在Where語句后面增加更多的AND語句來修改查詢字符串。為此,你需要和Limit FilterSet一起工作。

    FilterSet是一個過濾器對象數組,一個過濾器包括一個bean property和這個過濾器的值。或者,簡單的說就是用戶想要過濾的行和他們輸入的值。這使得它非常容易交互。service只需要迭代所有的 FilterSet并調用dao來拼接查詢語句。(譯者注:過濾的實現方式是:在Where后面增加And語句來改變查詢語句以達到對數據進行過濾的效果)

    private String filterQuery(FilterSet filterSet, String query) {
    if (!filterSet.isFiltered() || filterSet.isCleared()) {
    return query;
    }

    Filter filters[] = filterSet.getFilters();
    for (int i = 0; i < filters.length; i++) {
    Filter filter = filters[i];
    String property = filter.getProperty();
    String value = filter.getValue();
    query = presidentsDao.filterQuery(query, property, value);
    }

    return query;
    }

    query修改包括了filter信息,總行數。在一些情況下這就足夠,但是當用戶導出數據時仍然存在一個潛在的問題。為了保持高效 service不允許導出超出一個最大行數的數據。

    1.3.2. 取得Collection

    controller需要到第二條信息就是Collection。

    public Collection getPresidents(FilterSet filterSet, Sort sort, int rowEnd) {
    String patientsQuery = presidentsDao.getPresidentsQuery();
    String modPatientsQuery = filterQuery(filterSet, patientsQuery);
    modPatientsQuery = sortQuery(sort, modPatientsQuery);
    modPatientsQuery = presidentsDao.limitQuery(rowEnd, modPatientsQuery);
    return presidentsDao.getPresidents(modPatientsQuery);
    }

    和前面一樣,service和dao一起來過濾結果集。

    另外query字符串需要擴展ORDER BY語句以便數據按照正確的方式進行排序。Sort包含一個bean property和 sortOrder值(正序還是逆序)。service僅僅需要使用Sort來調用dao。

    private String sortQuery(Sort sort, String query) {
    if (!sort.isSorted()) {
    String defaultSortOrder = presidentsDao.getDefaultSortOrder();
    if (StringUtils.isNotBlank(defaultSortOrder)) {
    return query + defaultSortOrder;
    }

    return query;
    }

    String property = sort.getProperty();
    String sortOrder = sort.getSortOrder();

    return presidentsDao.sortQuery(query, property, sortOrder);
    }

    query字符串最后需要的修改就是增加數據庫特別的指令來limit將要被返回的結果集。這就是limitQuery() 方法的作用。

    1.4. DAO

    dao為service負責底層數據工作。

    1.4.1. 定義Query字符串

    為了真正理解dao,query字符串需要被展示。

    這就是得到數據的presidents query字符串:

    private final static String presidentsQuery = 
    " SELECT " +
    " president_id presidentId, " +
    " first_name firstName, " +
    " last_name lastName, " +
    " nick_name nickName, " +
    " concat(first_name, ' ',last_name) fullName, " +
    " term, " +
    " born, " +
    " died, " +
    " education, " +
    " career, " +
    " political_party politicalParty " +
    " FROM presidents ";

    這是得到總行數的query字符串:

    private final static String totalPresidentsQuery = 
    " SELECT count(*) FROM presidents ";

    1.4.2. Filter 和 Sort Query 字符串

    兩個最有趣的方法就是過濾和排序。

    filter看起來像這樣:

    public String filterQuery(String query, String property, String value) {
    StringBuffer result = new StringBuffer(query);

    if (query.indexOf("WHERE") == -1) {
    result.append(" WHERE 1 = 1 "); //stub WHERE clause so can just append AND clause
    }

    if (property.equals("fullName")) {
    result.append(" AND concat(first_name, ' ',last_name) like '%" + value + "%'");
    } else if (property.equals("nickName")) {
    result.append(" AND nick_name like '%" + value + "%'");
    } else {
    result.append(" AND " + property + " like '%" + value + "%'");
    }

    return result.toString();
    }

    filterQuery()方法需要增加正確的AND語句到query字符串。

    sort看起來非常類似:

    public String sortQuery(String query, String property, String sortOrder) {
    StringBuffer result = new StringBuffer(query + " ORDER BY ");

    if (property.equals("fullName")) {
    result.append("concat(first_name, ' ',last_name) " + sortOrder);
    } else {
    result.append(property + " " + sortOrder);
    }

    return result.toString();
    }

    sortQuery()方法需要增加正確的ORDER BY語句到query字符串。

    1.4.3. Limit Query String

    現在query字符串修改能夠正確的進行filter和sort,它還需要修改以便只取頁面顯示相關的數據。MySQL為s the limit命令。

    public String limitQuery(int rowEnd, String query) {
    return query + " limit " + rowEnd;
    }

    1.4.4. 取回總行數和Collection.

    service需要的唯一東西就是:總行數和Collection。

    public Collection getPresidents(final String query) {
    return jdbcTemplate.query(query, new ResultReader() {
    List results = new ArrayList();
    public List getResults() {
    return results;
    }

    public void processRow(ResultSet rs)
    throws SQLException {
    President president = new President();
    president.setPresidentId(new Integer(rs.getInt("presidentId")));
    president.setFirstName(rs.getString("firstName"));
    president.setLastName(rs.getString("lastName"));
    president.setNickName(rs.getString("nickName"));
    president.setFullName(rs.getString("fullName"));
    president.setTerm(rs.getString("term"));
    president.setBorn(rs.getDate("born"));
    president.setDied(rs.getDate("died"));
    president.setEducation(rs.getString("education"));
    president.setCareer(rs.getString("career"));
    president.setPoliticalParty(rs.getString("politicalParty"));
    results.add(president);
    }
    });
    }

    public int getTotalPresidents(final String query) {
    return jdbcTemplate.queryForInt(query);
    }

    ResultReader是一個幫助處理JDBC查詢的Spring特殊類,作為一個callback來處理JDBC ResultSet。jdbcTemplate是對JDBC連接的抽象。

    1.4.5. 默認的Sort順序

    最后,這是service需要的默認sort順序:

    public String getDefaultSortOrder() {
    return " ORDER BY concat(first_name, ' ', last_name) ";
    }

    posted on 2007-06-12 21:28 Jhonney 閱讀(317) 評論(0)  編輯  收藏 所屬分類: 轉載區

    主站蜘蛛池模板: 免费视频精品一区二区| 亚洲第一页在线视频| 亚洲av无码无线在线观看| 91香焦国产线观看看免费| 亚洲成?v人片天堂网无码| 亚洲中文字幕久久精品无码A | 高清免费久久午夜精品| 国产成人免费a在线视频app| 亚洲国产成人综合精品| 日韩黄色免费观看| 色爽黄1000部免费软件下载| 亚洲精品无码AV中文字幕电影网站| 一区二区三区AV高清免费波多| 国产亚洲AV夜间福利香蕉149| a级毛片毛片免费观看永久| 久久成人免费播放网站| 亚洲AV人人澡人人爽人人夜夜| 免费在线看黄网站| 亚洲伊人久久大香线蕉啊| 免费观看黄网站在线播放| 色婷婷六月亚洲综合香蕉| 亚洲免费一区二区| 久久精品免费观看| 亚洲一区二区三区深夜天堂| 猫咪免费人成在线网站| 国产日产亚洲系列| 亚洲a一级免费视频| 亚洲一区二区三区丝袜| 免费国产小视频在线观看| 青青操视频在线免费观看| 亚洲天堂中文字幕在线观看| 国产美女无遮挡免费视频| 国产99久久久久久免费看| 亚洲国产精品免费在线观看| 免费看的一级毛片| 国产午夜成人免费看片无遮挡| 亚洲AⅤ视频一区二区三区| 两个人的视频www免费| 亚洲人成电影在线观看网| 免费播放特黄特色毛片| 日韩免费在线视频|