【轉】jqGrid與Struts2的結合應用(五) —— 結合Action類進行數據查詢

轉至:http://blog.csdn.net/gengv/article/details/5725172

作者:gengv

 

這篇主要講的是jqGrid的查找功能。

根據官方文檔的介紹,jqGrid的查找功能分四種:

  • 工具條查詢;
  • 自定義查詢;
  • 單條件表單查詢;
  • 高級表單查詢(複雜條件查詢);


我個人認爲這樣劃分比較複雜,可以基本分爲兩大類,即:
表單查詢:包括單條件查詢和高級查詢(複雜條件查詢);
工具條查詢:包括工具條查詢和自定義查詢;

而這兩大類中,也以表單查詢更常用。

現在逐個說明一下(我改變了官方文檔的講解順序,我覺得自己的這個順序,更直觀,更靠近現實使用)。

 


1. 單條件表單查詢 

先從服務器端看起,爲了配合jqGrid的查詢功能,我們需要在JqGridBaseAction類中添加幾個成員變量。成員變量的名字必須和jqGrid的prmNames選項中定義的參數名相對應上(具體參考本系列文章的第一篇)。

改進後的JqGridBaseAction類代碼:

[java]  view plain copy
  1. package cn.gengv.struts2ex.jqGrid;  
  2.    
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5. import java.util.List;  
  6.    
  7. import com.byzl.hare.dao.impl.Criterion;  
  8. import com.byzl.hare.dao.impl.Criterion.CompareType;  
  9. import com.opensymphony.xwork2.ActionSupport;  
  10.    
  11. @SuppressWarnings("serial")  
  12. public abstract class JqGridBaseAction<T> extends ActionSupport {  
  13.     private List<T> gridModel = Collections.emptyList();  
  14.     private Integer rows = 0;  
  15.     private Integer page = 0;  
  16.     private Integer total = 0;  
  17.     private Integer record = 0;  
  18.     private String sord;  
  19.     private String sidx;  
  20.        
  21.     // (1)添加和查詢有關的成員變量search、searchField、searchString、searchOper  
  22.     private boolean search;  
  23.     private String searchField;  
  24.     private String searchString;  
  25.     private String searchOper;  
  26.    
  27.     public abstract int getResultSize();  
  28.     public abstract List<T> listResults(int from, int length);  
  29.        
  30.     // (2)添加用於根據條件進行查詢的方法  
  31.     public abstract int getResultSize(List<Criterion> criteria);  
  32.     public abstract List<T> listResults(List<Criterion> criteria, int from, int length);  
  33.    
  34.     public String refreshGridModel() {  
  35.         try {  
  36.             List<Criterion> criteria = Collections.emptyList();  
  37.                
  38.             // (3)如果search值爲true,則表明是查詢請求  
  39.             if(search == true) {  
  40.                    
  41.                 // (4)通過searchField、searchString、searchOper生成通用的查詢條件  
  42.                 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper);  
  43.               
  44.                 criteria = new ArrayList<Criterion>();  
  45.                   
  46.                 if(criterion != null) {  
  47.                     criteria.add(criterion);  
  48.                 }  
  49.             }  
  50.                
  51.             int from = rows * (page - 1);  
  52.             int length = rows;  
  53.                
  54.             List<T> results = Collections.emptyList();  
  55.                
  56.             if(!criteria.isEmpty()) {   // (5)如果criteria列表不爲空,則根據條件進行查詢  
  57.                 record = this.getResultSize(criteria);  
  58.                 results = this.listResults(criteria, from, length);  
  59.                   
  60.             } else {  
  61.                 record = this.getResultSize();  
  62.                 results = this.listResults(from, length);  
  63.                   
  64.             }  
  65.                
  66.             this.setGridModel(results);  
  67.             total = (int) Math.ceil((double) record / (double) rows);  
  68.             return SUCCESS;  
  69.         } catch (Exception e) {  
  70.             e.printStackTrace();  
  71.             this.addActionError(e.getMessage());  
  72.             return ERROR;  
  73.         }  
  74.     }  
  75.       
  76.     // (6)通過searchField、searchString、searchOper三個參數生成Criterion的方法  
  77.     public Criterion generateSearchCriterion(String searchField,  
  78.             String searchString, String searchOper) {  
  79.         Criterion criterion = null;  
  80.           
  81.         // (7)如果searchField、searchString、searchOper均不爲null,且searchString不爲空字符串時,則創建Criterion  
  82.         if (searchField != null && searchString != null  
  83.                 & searchString.length() > 0 && searchOper != null) {  
  84.             if ("eq".equals(searchOper)) {  
  85.                 criterion = Criterion.getEqualCriterion(searchField,  
  86.                         searchString, null);  
  87.             } else if ("ne".equals(searchOper)) {  
  88.                 criterion = Criterion.getCompareCriterion(CompareType.NE,  
  89.                         searchField, searchString, null);  
  90.             } else if ("lt".equals(searchOper)) {  
  91.                 criterion = Criterion.getCompareCriterion(CompareType.LT,  
  92.                         searchField, searchString, null);  
  93.             } else if ("le".equals(searchOper)) {  
  94.                 criterion = Criterion.getCompareCriterion(CompareType.LTE,  
  95.                         searchField, searchString, null);  
  96.             } else if ("gt".equals(searchOper)) {  
  97.                 criterion = Criterion.getCompareCriterion(CompareType.GT,  
  98.                         searchField, searchString, null);  
  99.             } else if ("ge".equals(searchOper)) {  
  100.                 criterion = Criterion.getCompareCriterion(CompareType.GTE,  
  101.                         searchField, searchString, null);  
  102.             } else if ("bw".equals(searchOper)) {  
  103.                 criterion = Criterion.getLikeCriterion(searchField,  
  104.                         searchString + "%"null);  
  105.             } else if ("bn".equals(searchOper)) {  
  106.                 criterion = Criterion.getNotLikeCriterion(searchField,  
  107.                         searchString + "%"null);  
  108.             } else if ("ew".equals(searchOper)) {  
  109.                 criterion = Criterion.getLikeCriterion(searchField, "%"  
  110.                         + searchString, null);  
  111.             } else if ("en".equals(searchOper)) {  
  112.                 criterion = Criterion.getNotLikeCriterion(searchField, "%"  
  113.                         + searchString, null);  
  114.             } else if ("cn".equals(searchOper)) {  
  115.                 criterion = Criterion.getLikeCriterion(searchField, "%"  
  116.                         + searchString + "%"null);  
  117.             } else if ("nc".equals(searchOper)) {  
  118.                 criterion = Criterion.getNotLikeCriterion(searchField, "%"  
  119.                         + searchString + "%"null);  
  120.             }  
  121.         }  
  122.         return criterion;  
  123.     }  
  124.       
  125.     // getter和setter  
  126.     ...  
  127. }  

 

說明:

  • (1)處添加了關於查詢使用到的成員變量,這些成員變量會接收從客戶端jqGrid傳來的參數,這些參數的名稱都是由jqGrid的prmNames選項定義的;
  • (2)處添加了兩個方法,用於根據條件列表,進行數據記錄查詢;(關於條件列表List<Criterion>稍後介紹);
  • (3)處判斷成員變量search的值,如果是查詢請求,jqGrid會發送search值爲true的請求;
  • (4)(6)(7)通過searchField、searchString、searchOper三個參數生成Criterion的方法;以前在學習Hibernate的時候,裏面就介紹過使用Criterion的方式;有的朋友對Hibernate奉若神明,但我一直對Hibernate的靈活度不太滿意;不過這種將查詢條件抽象出來的思路還是值得借鑑的。因此,我雖然後臺使用的是Spring的JdbcTemplate,但爲了抽象化Dao內的操作,我自己寫了一個Criterion類(具體代碼在後面)。使用這個Criterion列表來簡化查詢條件在各個層的傳遞。
  • (5)如果條件列表不爲空,則調用新加入的條件查詢方法。

Criterion類的代碼:

 

[java]  view plain copy
  1. package com.byzl.hare.dao.impl;  
  2. import java.util.ArrayList;  
  3. import java.util.Collections;  
  4. import java.util.List;  
  5. public class Criterion {  
  6.     public static enum CriterionType {  
  7.         EQUAL, LIKE, COMPARE, NOT_LIKE  
  8.     }  
  9.     public static enum CompareType {  
  10.         GT, GTE, LT, LTE, EQ, NE  
  11.     }  
  12.     private CriterionType criterionType;  
  13.     private String tableName;  
  14.     private String field;  
  15.     private Object value;  
  16.     // 將Criteria轉換爲SQL條件語句  
  17.     public static String convertToSql(List<Criterion> criteria) {  
  18.         String criteriaString = "";  
  19.         StringBuilder sb = new StringBuilder();  
  20.         for (Criterion criterion : criteria) {  
  21.             String prefix = criterion.getFieldPrefix();  
  22.             switch (criterion.getCriterionType()) {  
  23.             case EQUAL:  
  24.                 sb.append(prefix + criterion.getField() + "=? and ");  
  25.                 break;  
  26.             case LIKE:  
  27.                 sb.append(prefix + criterion.getField() + " like ? and ");  
  28.                 break;  
  29.                   
  30.             case NOT_LIKE:  
  31.                 sb.append(prefix + criterion.getField() + " not like ? and ");  
  32.                 break;  
  33.             case COMPARE:  
  34.                 CompareType compareType = ((CompareCriterion) criterion)  
  35.                         .getCompareType();  
  36.                 switch (compareType) {  
  37.                 case EQ:  
  38.                     sb.append(prefix + criterion.getField() + "=? and ");  
  39.                     break;  
  40.                 case NE:  
  41.                     sb.append(prefix + criterion.getField() + "<>? and ");  
  42.                     break;  
  43.                 case GT:  
  44.                     sb.append(prefix + criterion.getField() + ">? and ");  
  45.                     break;  
  46.                 case GTE:  
  47.                     sb.append(prefix + criterion.getField() + ">=? and ");  
  48.                     break;  
  49.                 case LT:  
  50.                     sb.append(prefix + criterion.getField() + "<? and ");  
  51.                     break;  
  52.                 case LTE:  
  53.                     sb.append(prefix + criterion.getField() + "<=? and ");  
  54.                     break;  
  55.                 }  
  56.                 break;  
  57.             }  
  58.         }  
  59.         int i = -1;  
  60.         if ((i = sb.lastIndexOf(" and ")) != -1) {  
  61.             criteriaString = sb.substring(0, i);  
  62.         }  
  63.         return criteriaString;  
  64.     }  
  65.     // 將Criteria各條件的值轉換爲List<Object>  
  66.     public static List<Object> getCriteriaValues(List<Criterion> criteria) {  
  67.         List<Object> criteriaValues = criteria.isEmpty() ? Collections  
  68.                 .emptyList() : new ArrayList<Object>();  
  69.         for (Criterion criterion : criteria) {  
  70.             criteriaValues.add(criterion.getValue());  
  71.         }  
  72.         return criteriaValues;  
  73.     }  
  74.     public CriterionType getCriterionType() {  
  75.         return criterionType;  
  76.     }  
  77.     public void setCriterionType(CriterionType criterionType) {  
  78.         this.criterionType = criterionType;  
  79.     }  
  80.     public String getField() {  
  81.         return field;  
  82.     }  
  83.     public void setField(String field) {  
  84.         this.field = field;  
  85.     }  
  86.     public Object getValue() {  
  87.         return value;  
  88.     }  
  89.     public void setValue(Object value) {  
  90.         this.value = value;  
  91.     }  
  92.     public static Criterion getCompareCriterion(CompareType compareType,  
  93.             String field, Object value, String tableName) {  
  94.         CompareCriterion compareCriterion = new CompareCriterion();  
  95.         compareCriterion.setCriterionType(CriterionType.COMPARE);  
  96.         compareCriterion.setCompareType(compareType);  
  97.         compareCriterion.setField(field);  
  98.         compareCriterion.setValue(value);  
  99.         compareCriterion.setTableName(tableName);  
  100.         return compareCriterion;  
  101.     }  
  102.     public static Criterion getLikeCriterion(String field, Object value,  
  103.             String tableName) {  
  104.         LikeCriterion likeCriterion = new LikeCriterion();  
  105.         likeCriterion.setCriterionType(CriterionType.LIKE);  
  106.         likeCriterion.setField(field);  
  107.         likeCriterion.setValue(value);  
  108.         likeCriterion.setTableName(tableName);  
  109.         return likeCriterion;  
  110.     }  
  111.       
  112.     public static Criterion getNotLikeCriterion(String field, Object value,  
  113.             String tableName) {  
  114.         NotLikeCriterion notLikeCriterion = new NotLikeCriterion();  
  115.         notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE);  
  116.         notLikeCriterion.setField(field);  
  117.         notLikeCriterion.setValue(value);  
  118.         notLikeCriterion.setTableName(tableName);  
  119.         return notLikeCriterion;  
  120.     }  
  121.     public static Criterion getEqualCriterion(String field, Object value,  
  122.             String tableName) {  
  123.         EqualCriterion equalCriterion = new EqualCriterion();  
  124.         equalCriterion.setCriterionType(CriterionType.EQUAL);  
  125.         equalCriterion.setField(field);  
  126.         equalCriterion.setValue(value);  
  127.         equalCriterion.setTableName(tableName);  
  128.         return equalCriterion;  
  129.     }  
  130.     public static class LikeCriterion extends Criterion {  
  131.     }  
  132.       
  133.     public static class NotLikeCriterion extends Criterion {  
  134.     }  
  135.     public static class EqualCriterion extends Criterion {  
  136.     }  
  137.     public static class CompareCriterion extends Criterion {  
  138.         private CompareType compareType;  
  139.         public CompareType getCompareType() {  
  140.             return compareType;  
  141.         }  
  142.         public void setCompareType(CompareType compareType) {  
  143.             this.compareType = compareType;  
  144.         }  
  145.     }  
  146.     public String getTableName() {  
  147.         return tableName;  
  148.     }  
  149.     public void setTableName(String tableName) {  
  150.         this.tableName = tableName;  
  151.     }  
  152.     public String getFieldPrefix() {  
  153.         return (tableName == null || tableName.length() == 0) ? "" : tableName  
  154.                 + ".";  
  155.     }  
  156. }  

 

簡要說明一下:

  • 我把Criterion分成4類:EqualCriterion、CompareCriterion、LikeCriterion、NotLikeCriterion。(具體劃分方式全爲使用方便)
  • 另外還有兩個靜態方法:convertToSql和getCriteriaValues,用來將Criterion列表轉化爲JdbcTemplate需要的SQL子句和參數列表。


回到ListContactsAction,代碼如下:

 

[java]  view plain copy
  1. package cn.gengv.struts2ex.jqGrid;  
  2.    
  3. import java.util.Collections;  
  4. import java.util.List;  
  5. import com.byzl.hare.dao.impl.Criterion;  
  6. import com.byzl.hare.model.Contact;  
  7. import com.byzl.hare.service.ContactService;  
  8.    
  9. @SuppressWarnings("serial")  
  10. public class ListContactsAction extends JqGridBaseAction<Contact> {  
  11.       
  12.     private ContactService contactService;  
  13.       
  14.     @Override  
  15.     public String execute() {  
  16.         return this.refreshGridModel();  
  17.     }  
  18.       
  19.     @Override  
  20.     public int getResultSize() {  
  21.         return this.contactService.queryResultsCount(null);  
  22.     }  
  23.     @Override  
  24.     public List<Contact> listResults(int from, int length) {  
  25.         return this.contactService.queryByPage(null, from, length);  
  26.     }  
  27.       
  28.     @Override  
  29.     public int getResultSize(List<Criterion> criteria) {  
  30.         return this.contactService.queryResultsCount(criteria);  
  31.     }  
  32.       
  33.     @Override  
  34.     public List<Contact> listResults(List<Criterion> criteria, int from, int length) {  
  35.         List<Contact> results = Collections.emptyList();  
  36.           
  37.         results = this.contactService.queryByPage(criteria, from, length);  
  38.           
  39.         return results;  
  40.     }  
  41.    
  42.     public void setContactService(ContactService contactService) {  
  43.         this.contactService = contactService;  
  44.     }  
  45. }  

 

 

OK,服務器端的工作就先這樣了,應對單條件查詢已經足夠了。再來看看客戶端需要什麼特別的。

 

jqGrid的單條件查詢和高級查詢(複雜條件查詢)都是基於表單的查詢,使用的都是jqGrid的searchGrid方法:
    $("#grid_id").searchGrid( options ); 
或者
    $("#grid_id").jqGrid('searchGrid', options ); 
    
注:要想使用searchGrid方法,在下載jqGrid的時候,必須包含Common, Form Edit, Search Plugin的模塊。

在Navigator按鈕欄中的查詢按鈕,默認就是調用這個方法。

 

searchGrid也有很多選項,在language文件(grid.locale-xx.js)中,有關於這些選項的默認值定義。下面介紹一下主要常用的選項:

  • afterShowSearch :用於定義每次查詢對話框顯示之後,要執行的事件函數;
  • beforeShowSearch :用於定義每次查詢對話框顯示之前,要執行的事件函數;
  • caption :查詢對話框的標題;
  • closeAfterSearch :如果設爲true,則每次在查詢對話框中點擊「查詢」按鈕完成查詢後,對話框都會被關閉;默認爲false;
  • closeAfterReset :如果設爲true,則每次在查詢對話框中點擊「重置」按鈕完成查詢後,對話框都會被關閉;默認爲false;
  • closeOnEscape :如果設爲true,則當按ESC鍵的時候,對話框會被關閉;默認爲false;
  • Find :查詢對話框裏「查詢」按鈕上的文本;
  • Reset :查詢對話框裏「重置」按鈕上的文本;
  • sopt :用來設置通用的查詢規則,如['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'];如果爲設置,則使用全部規則;
  • odata :用來翻譯sopt中規則的對應數組;
  • onClose :當查詢對話框關閉時,將要執行的事件函數。可以返回true或false;如果返回false,則查詢對話框不會被關閉。
  • onInitializeSearch :當查詢對話框創建時,將要執行的事件函數。
  • recreateFilter :如果設置爲true,則當動態改變colModel的屬性時,重建查詢並解除時間綁定。
  • sField, sOper, sValue :當提交查詢請求時,對應着所包含的有關於查詢的參數;默認值分別是'searchField','searchOper','searchString'。

以上這些就是關於單條件查詢的選項;關於複雜條件查詢的選項稍後介紹。

注意:在searchGrid方法中設定這些選項,和在navGrid方法的prmSearch參數中設置這些選項(參見上一篇),作用效果是相同的。

 

 

[javascript]  view plain copy
  1. var singleCriterionSearch = function() {  
  2.     $("#gridTable").jqGrid("searchGrid", {  
  3.         caption: "查找",  
  4.         Find: "Go!",  
  5.         closeAfterSearch: true  
  6.     });  
  7. };  

 

等同於

 

[javascript]  view plain copy
  1. $("#gridTable").jqGrid("navGrid""#gridPager", {},{},{},{},  
  2.     {   // 與查詢相關的prmSearch參數  
  3.         caption: "查找",  
  4.         Find: "Go!",  
  5.         closeAfterSearch: true  
  6.     },{});  

 

 

當點擊查詢對話框中的「查詢」按鈕的時候,jqGrid會向Server提交一個請求,例如:
http://localhost:8085/Hare/jqGridTest/jqGrid05.action?search=true&nd=1278685481936&rows=15&page=1&sidx=&sord=asc&searchField=id&searchString=9000&searchOper=ge

 

 

 

2. 高級查詢(複雜條件表單查詢) 

在上一部分已經提到了,單條件表單查詢和高級查詢(複雜條件表單查詢)都是用的是searchGrid方法,只不過是傳入的選項值有所不同而已。其中最重要的一個選項就是multipleSearch。

下面就來詳細介紹在searchGrid中,與複雜條件查詢相關的主要選項:

  • multipleSearch :如果設置爲true,則**複雜條件查詢;默認爲false。
  • groupOps :默認通常爲[ { op: "AND", text: "all" }, { op: "OR", text: "any" } ],表示需要滿足多重條件的方式,例如滿足所有查詢條件或者滿足任意查詢條件。
  • sFilter :對應着在複雜查詢提交請求時,對應的參數名;默認爲filters。

將javascript代碼改爲:

 

[javascript]  view plain copy
  1. $("#gridTable").jqGrid("navGrid""#gridPager", {},{},{},{},  
  2.     {   // 與查詢相關的prmSearch參數  
  3.         caption: "查找",  
  4.         Find: "Go!",  
  5.         closeAfterSearch: true,  
  6.         multipleSearch: true,  
  7.         groupOps: [{ op: "AND", text: "全部" }]  
  8.     },{});  

 

或者

 

[javascript]  view plain copy
  1. var complexCriteriaSearch = function() {  
  2.     $("#gridTable").jqGrid("searchGrid", {  
  3.         caption: "查找",  
  4.         Find: "Go!",  
  5.         closeAfterSearch: true,  
  6.         multipleSearch: true,  
  7.         groupOps: [{ op: "AND", text: "全部" }]  
  8.     });  
  9. };  

 

 

 

 

除了選項上的不同以外,客戶端的另一個不同之處在於,向Server端傳遞的參數不同。在第一部分的例子中可以看到,當單條件查詢提交請求的時候,傳遞的參數是:
http://localhost:8085/Hare/jqGridTest/jqGrid05.action?search=true&nd=1278685481936&rows=15&page=1&sidx=&sord=asc&searchField=id&searchString=9000&searchOper=ge

 

即:

[javascript]  view plain copy
  1. nd: 1278688214496  
  2. page:   1  
  3. rows:   15  
  4. search: true  
  5. searchField:    id  
  6. searchOper: ge  
  7. searchString:   9000  
  8. sidx:     
  9. sord:   asc  

 

而複雜條件的查詢的參數是下面這種形式:
http://localhost:8085/Hare/jqGridTest/jqGrid05.action?search=true&nd=1278688110637&rows=15&page=1&sidx=&sord=asc&filters=%7B%22groupOp%22%3A%22AND%22%2C%22rules%22%3A%5B%7B%22field%22%3A%22id%22%2C%22op%22%3A%22le%22%2C%22data%22%3A%221500%22%7D%2C%7B%22field%22%3A%22lastName%22%2C%22op%22%3A%22bw%22%2C%22data%22%3A%22LN-3%22%7D%2C%7B%22field%22%3A%22email%22%2C%22op%22%3A%22cn%22%2C%22data%22%3A%22sy%22%7D%5D%7D

 

即:

 

[javascript]  view plain copy
  1. filters:    {"groupOp":"AND","rules":[{"field":"id","op":"le","data":"1500"},{"field":"lastName","op":"bw","data":"LN-3"},{"field":"email","op":"cn","data":"sy"}]}  
  2. nd: 1278688110637  
  3. page:   1  
  4. rows:   15  
  5. search: true  
  6. sidx:     
  7. sord:   asc  

 

 

我們可以發現,傳遞的參數中除了search以外,searchField、searchOper、searchString都不見了,取而代之的是一個filters參數。filters參數查詢條件以及複雜條件的匹配方式封裝成了json的格式,然後傳遞給Server。

針對這種格式的參數,繼續使用第一個例子中的JqGridBaseAction類的查詢方式,顯然是無法應對的。我們必須再次改進JqGridBaseAction類。而關鍵之處就是如何解析這個json格式的filters參數。

 

爲此,我引入了json-lib庫(http://json-lib.sourceforge.net/ ),其他的關於json的java庫還可以訪問http://www.json.org/ 。

 

在JqGridBaseAction類中添加方法generateSearchCriteriaFromFilters(),來將filters參數解析爲Criterion列表。

 

[java]  view plain copy
  1. public List<Criterion> generateSearchCriteriaFromFilters(String filters) {  
  2.     List<Criterion> criteria = new ArrayList<Criterion>();  
  3.       
  4.     JSONObject jsonObject = JSONObject.fromObject(filters);  
  5.       
  6.     JSONArray rules = jsonObject.getJSONArray("rules");  
  7.       
  8.     for(Object obj : rules) {  
  9.         JSONObject rule = (JSONObject) obj;  
  10.           
  11.         String field = rule.getString("field");  
  12.         String op = rule.getString("op");  
  13.         String data = rule.getString("data");  
  14.           
  15.         Criterion criterion = this.generateSearchCriterion(field, data, op);  
  16.           
  17.         if(criterion != null) {  
  18.             criteria.add(criterion);  
  19.         }  
  20.     }  
  21.       
  22.     return criteria;  
  23. }  

 

 

其餘部分的代碼:

 

[java]  view plain copy
  1. package cn.gengv.struts2ex.jqGrid;  
  2.    
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5. import java.util.List;  
  6. import net.sf.json.JSONArray;  
  7. import net.sf.json.JSONObject;  
  8.    
  9. import com.byzl.hare.dao.impl.Criterion;  
  10. import com.byzl.hare.dao.impl.Criterion.CompareType;  
  11. import com.opensymphony.xwork2.ActionSupport;  
  12.    
  13. @SuppressWarnings("serial")  
  14. public abstract class JqGridBaseAction<T> extends ActionSupport {  
  15.     private List<T> gridModel = Collections.emptyList();  
  16.     private Integer rows = 0;  
  17.     private Integer page = 0;  
  18.     private Integer total = 0;  
  19.     private Integer record = 0;  
  20.     private String sord;  
  21.     private String sidx;  
  22.        
  23.     private boolean search;  
  24.     private String searchField;  
  25.     private String searchString;  
  26.     private String searchOper;  
  27.    
  28.     public abstract int getResultSize();  
  29.     public abstract List<T> listResults(int from, int length);  
  30.       
  31.     // (1)添加filters成員變量  
  32.     private String filters;  
  33.        
  34.     public abstract int getResultSize(List<Criterion> criteria);  
  35.     public abstract List<T> listResults(List<Criterion> criteria, int from, int length);  
  36.       
  37.     public String refreshGridModel() {  
  38.         try {  
  39.             List<Criterion> criteria = Collections.emptyList();  
  40.                
  41.             if(search == true) {  
  42.                 criteria = new ArrayList<Criterion>();  
  43.                   
  44.                 // (2)將Filter轉化爲Criterion列表,並加入總的Criterion列表  
  45.                 if(filters != null && filters.length()>0) {  
  46.                     criteria.addAll(this.generateSearchCriteriaFromFilters(filters));  
  47.                 }  
  48.                    
  49.                 // (3)將searchField、searchString、searchOper轉化爲Criterion,並加入總的Criterion列表  
  50.                 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper);  
  51.                 if(criterion != null) {  
  52.                     criteria.add(criterion);  
  53.                 }  
  54.             }  
  55.                
  56.             int from = rows * (page - 1);  
  57.             int length = rows;  
  58.                
  59.             List<T> results = Collections.emptyList();  
  60.                
  61.             if(!criteria.isEmpty()) {  
  62.                 record = this.getResultSize(criteria);  
  63.                 results = this.listResults(criteria, from, length);  
  64.                   
  65.             } else {  
  66.                 record = this.getResultSize();  
  67.                 results = this.listResults(from, length);  
  68.                   
  69.             }  
  70.                
  71.             this.setGridModel(results);  
  72.             total = (int) Math.ceil((double) record / (double) rows);  
  73.             return SUCCESS;  
  74.         } catch (Exception e) {  
  75.             e.printStackTrace();  
  76.             this.addActionError(e.getMessage());  
  77.             return ERROR;  
  78.         }  
  79.     }  
  80.        
  81.        
  82.     public Criterion generateSearchCriterion(String searchField,  
  83.             String searchString, String searchOper) {  
  84.         ...  
  85.           
  86.     }  
  87.       
  88.     public List<Criterion> generateSearchCriteriaFromFilters(String filters) {  
  89.         List<Criterion> criteria = new ArrayList<Criterion>();  
  90.           
  91.         JSONObject jsonObject = JSONObject.fromObject(filters);  
  92.           
  93.         JSONArray rules = jsonObject.getJSONArray("rules");  
  94.           
  95.         for(Object obj : rules) {  
  96.             JSONObject rule = (JSONObject) obj;  
  97.               
  98.             String field = rule.getString("field");  
  99.             String op = rule.getString("op");  
  100.             String data = rule.getString("data");  
  101.               
  102.             Criterion criterion = this.generateSearchCriterion(field, data, op);  
  103.               
  104.             if(criterion != null) {  
  105.                 criteria.add(criterion);  
  106.             }  
  107.         }  
  108.           
  109.         return criteria;  
  110.     }  
  111.     //getter和setter  
  112.     ...  
  113. }  

 

 

經過如上修改,JqGridBaseAction類可以接受單條件查詢和複雜條件查詢請求了。

 


3. 工具條查詢 

再來看看工具條查詢,工具條查詢主要依靠jqGrid的filterToolbar方法:
    $("#grid_id").filterToolbar(options); 
或者
    $("#grid_id").jqGrid('filterToolbar',options);

 


主要的選項包括:

  • autosearch :當在查詢工具條的輸入框中點擊回車,或者select選擇框中的值發生改變的時候,search參數將設爲true,並觸發ajax請求。默認爲true。
  • beforeSearch :查詢前觸發的事件函數。如果返回true,則不繼續出發查詢;在這種情況中,可以自己構建查詢參數來查詢數據。其他返回類型,都會觸發查詢。
  • afterSearch :查詢後觸發的事件函數。
  • beforeClear :當清理輸入值之前觸發的事件函數(例如clearToolbar方法(稍後介紹))。如果設爲true,則不繼續觸發清理查詢事件;這種情況下,可以自己構建參數來從Server獲得數據。其他返回類型,都會觸發事件。
  • afterClear :當清理輸入值之後觸發的事件函數(例如clearToolbar方法(稍後介紹))。
  • searchOnEnter :如果設爲true,就參考autosearch;如果設爲false,則輸入字符後,立即進行查詢。
  • stringResult :決定如何發送查詢參數,如果設爲false,則按key:value對的形式,發送參數;如果設爲true,則按照複雜條件查詢的方式,發送查詢參數(其中包含json格式的filters參數)。
  • groupOp :只有stringResult爲true時,此選項纔有效;其值可以爲AND或OR;默認爲AND。

注:sopt選項在此方法中不會起作用。

 

在stringResult不爲true的情況下,查詢參數是這樣的:

 

[javascript]  view plain copy
  1. firstName:  FN-cjxxxds3  
  2. lastName:   LN-3iviu7o  
  3. nd: 1278692114137  
  4. page:   1  
  5. rows:   15  
  6. search: true  
  7. sidx:     
  8. sord:   asc  
  9. telNo:  TEL-gzbn1w  

 

 

而當stringResult設爲true的情況下,查詢參數會按照複雜條件查詢的方式發送:

 

[javascript]  view plain copy
  1. filters:    {"groupOp":"AND","rules":[{"field":"lastName","op":"bw","data":"LN-3iviu7o"},{"field":"firstName","op":"bw","data":"FN-cjxxxds3"},{"field":"telNo","op":"bw","data":"TEL-gzbn1w"}]}  
  2. nd: 1278692302168  
  3. page:   1  
  4. rows:   15  
  5. search: true  
  6. sidx:     
  7. sord:   asc  

 

 

工具條查詢相關的附加方法:

  • triggerToolbar :當調用此方法,search參數會變爲true,並向Server提交ajax請求;
  • clearToolbar :當調用此方法,清除輸入值,並將search參數設爲false,向Server提交ajax請求;
  • toggleToolbar :打開/關閉查詢工具條。

注意以上三種附加方法的調用方式爲:
$("#gridTable")[0].triggerToolbar();

注:一定不能少了「[0]」。

 

 

4. 自定義查詢 

雖然官方文檔裏將這種查詢方式成爲自定義查詢,但其實就是工具條查詢的變種。無非是改變了查詢工具條的位置以及構建方式。

首先需要在html頁面中建立一個區域,用於存放輸入查詢條件的表單,例如:
<div id="mysearch"></div> 

然後構建查詢工具條:
    $("#mysearch").filterGrid('#grid_id',options); 
或者
    $("#mysearch").jqGrid('filterGrid','#grid_id',options); 
    
主要選項:

  • gridModel :默認爲false;如果設爲true,則使用colModel中的name、index、edittype、editoptions、search等屬性來構建查詢(只有colModel的search屬性爲true的列會被用來構建查詢表單);如果此項被設爲false,則應構建一個filterModel數組來處理查詢。
  • gridNames :默認爲false;僅當gridModel爲true的時候有效,當此項設爲true時,會從jqGrid的colNames選項或得每列的標題。
  • filterModel :當gridModel爲false是應該使用該屬性構建查詢表單。(稍後介紹)
  • formtype :定義查詢表單應該是橫向排列的還是縱向排列的。
  • autosearch :設爲true時,當輸入框中回車或select選擇框值改變時,觸發查詢;設爲false時,通過按鈕觸發查詢。默認爲true。
  • formclass/tableclass/buttonclass :應用於表單的樣式。


其他選項,可在真正使用時,查詢文檔。

filterModel: [

{label:'LableFild', name: 'colname', stype: 'select', defval: 'default_value', surl: 'someurl', sopt:{optins for the select}},
… 
]

注:由於傳遞查詢參數的方式與工具條查詢在stringResult不爲true的情況下類似,即key:value對的格式,因此這種查詢方式對於JqGridBaseAction類來說用處不大。

附加方法:

  • triggerSearch :觸發查詢;
  • clearSearch :清除查詢表單中的值,並使用空表單或默認值從Server獲得數據。

var sg = jQuery("#mysearch").filterGrid(...)[0]; sg.triggerSearch();sg.clearSearch();sg.triggerSearch();