`

jqGrid与Struts2的结合应用(五) —— 结合Action类进行数据查询

 
阅读更多

这篇主要讲的是jqGrid的查找功能。

根据官方文档的介绍,jqGrid的查找功能分四种:

  • 工具条查询;
  • 自定义查询;
  • 单条件表单查询;
  • 高级表单查询(复杂条件查询);


我个人认为这样划分比较复杂,可以基本分为两大类,即:
表单查询:包括单条件查询和高级查询(复杂条件查询);
工具条查询:包括工具条查询和自定义查询;

而这两大类中,也以表单查询更常用。

现在逐个说明一下(我改变了官方文档的讲解顺序,我觉得自己的这个顺序,更直观,更靠近现实使用)。


1. 单条件表单查询

先从服务器端看起,为了配合jqGrid的查询功能,我们需要在JqGridBaseAction类中添加几个成员变量。成员变量的名字必须和jqGrid的prmNames选项中定义的参数名相对应上(具体参考本系列文章的第一篇)。

改进后的JqGridBaseAction类代码:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. importcom.byzl.hare.dao.impl.Criterion;
  6. importcom.byzl.hare.dao.impl.Criterion.CompareType;
  7. importcom.opensymphony.xwork2.ActionSupport;
  8. @SuppressWarnings("serial")
  9. publicabstractclassJqGridBaseAction<T>extendsActionSupport{
  10. privateList<T>gridModel=Collections.emptyList();
  11. privateIntegerrows=0;
  12. privateIntegerpage=0;
  13. privateIntegertotal=0;
  14. privateIntegerrecord=0;
  15. privateStringsord;
  16. privateStringsidx;
  17. //(1)添加和查询有关的成员变量search、searchField、searchString、searchOper
  18. privatebooleansearch;
  19. privateStringsearchField;
  20. privateStringsearchString;
  21. privateStringsearchOper;
  22. publicabstractintgetResultSize();
  23. publicabstractList<T>listResults(intfrom,intlength);
  24. //(2)添加用于根据条件进行查询的方法
  25. publicabstractintgetResultSize(List<Criterion>criteria);
  26. publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
  27. publicStringrefreshGridModel(){
  28. try{
  29. List<Criterion>criteria=Collections.emptyList();
  30. //(3)如果search值为true,则表明是查询请求
  31. if(search==true){
  32. //(4)通过searchField、searchString、searchOper生成通用的查询条件
  33. Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
  34. criteria=newArrayList<Criterion>();
  35. if(criterion!=null){
  36. criteria.add(criterion);
  37. }
  38. }
  39. intfrom=rows*(page-1);
  40. intlength=rows;
  41. List<T>results=Collections.emptyList();
  42. if(!criteria.isEmpty()){//(5)如果criteria列表不为空,则根据条件进行查询
  43. record=this.getResultSize(criteria);
  44. results=this.listResults(criteria,from,length);
  45. }else{
  46. record=this.getResultSize();
  47. results=this.listResults(from,length);
  48. }
  49. this.setGridModel(results);
  50. total=(int)Math.ceil((double)record/(double)rows);
  51. returnSUCCESS;
  52. }catch(Exceptione){
  53. e.printStackTrace();
  54. this.addActionError(e.getMessage());
  55. returnERROR;
  56. }
  57. }
  58. //(6)通过searchField、searchString、searchOper三个参数生成Criterion的方法
  59. publicCriteriongenerateSearchCriterion(StringsearchField,
  60. StringsearchString,StringsearchOper){
  61. Criterioncriterion=null;
  62. //(7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion
  63. if(searchField!=null&&searchString!=null
  64. &searchString.length()>0&&searchOper!=null){
  65. if("eq".equals(searchOper)){
  66. criterion=Criterion.getEqualCriterion(searchField,
  67. searchString,null);
  68. }elseif("ne".equals(searchOper)){
  69. criterion=Criterion.getCompareCriterion(CompareType.NE,
  70. searchField,searchString,null);
  71. }elseif("lt".equals(searchOper)){
  72. criterion=Criterion.getCompareCriterion(CompareType.LT,
  73. searchField,searchString,null);
  74. }elseif("le".equals(searchOper)){
  75. criterion=Criterion.getCompareCriterion(CompareType.LTE,
  76. searchField,searchString,null);
  77. }elseif("gt".equals(searchOper)){
  78. criterion=Criterion.getCompareCriterion(CompareType.GT,
  79. searchField,searchString,null);
  80. }elseif("ge".equals(searchOper)){
  81. criterion=Criterion.getCompareCriterion(CompareType.GTE,
  82. searchField,searchString,null);
  83. }elseif("bw".equals(searchOper)){
  84. criterion=Criterion.getLikeCriterion(searchField,
  85. searchString+"%",null);
  86. }elseif("bn".equals(searchOper)){
  87. criterion=Criterion.getNotLikeCriterion(searchField,
  88. searchString+"%",null);
  89. }elseif("ew".equals(searchOper)){
  90. criterion=Criterion.getLikeCriterion(searchField,"%"
  91. +searchString,null);
  92. }elseif("en".equals(searchOper)){
  93. criterion=Criterion.getNotLikeCriterion(searchField,"%"
  94. +searchString,null);
  95. }elseif("cn".equals(searchOper)){
  96. criterion=Criterion.getLikeCriterion(searchField,"%"
  97. +searchString+"%",null);
  98. }elseif("nc".equals(searchOper)){
  99. criterion=Criterion.getNotLikeCriterion(searchField,"%"
  100. +searchString+"%",null);
  101. }
  102. }
  103. returncriterion;
  104. }
  105. //getter和setter
  106. ...
  107. }

说明:

  • (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类的代码:

  1. packagecom.byzl.hare.dao.impl;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. publicclassCriterion{
  6. publicstaticenumCriterionType{
  7. EQUAL,LIKE,COMPARE,NOT_LIKE
  8. }
  9. publicstaticenumCompareType{
  10. GT,GTE,LT,LTE,EQ,NE
  11. }
  12. privateCriterionTypecriterionType;
  13. privateStringtableName;
  14. privateStringfield;
  15. privateObjectvalue;
  16. //将Criteria转换为SQL条件语句
  17. publicstaticStringconvertToSql(List<Criterion>criteria){
  18. StringcriteriaString="";
  19. StringBuildersb=newStringBuilder();
  20. for(Criterioncriterion:criteria){
  21. Stringprefix=criterion.getFieldPrefix();
  22. switch(criterion.getCriterionType()){
  23. caseEQUAL:
  24. sb.append(prefix+criterion.getField()+"=?and");
  25. break;
  26. caseLIKE:
  27. sb.append(prefix+criterion.getField()+"like?and");
  28. break;
  29. caseNOT_LIKE:
  30. sb.append(prefix+criterion.getField()+"notlike?and");
  31. break;
  32. caseCOMPARE:
  33. CompareTypecompareType=((CompareCriterion)criterion)
  34. .getCompareType();
  35. switch(compareType){
  36. caseEQ:
  37. sb.append(prefix+criterion.getField()+"=?and");
  38. break;
  39. caseNE:
  40. sb.append(prefix+criterion.getField()+"<>?and");
  41. break;
  42. caseGT:
  43. sb.append(prefix+criterion.getField()+">?and");
  44. break;
  45. caseGTE:
  46. sb.append(prefix+criterion.getField()+">=?and");
  47. break;
  48. caseLT:
  49. sb.append(prefix+criterion.getField()+"<?and");
  50. break;
  51. caseLTE:
  52. sb.append(prefix+criterion.getField()+"<=?and");
  53. break;
  54. }
  55. break;
  56. }
  57. }
  58. inti=-1;
  59. if((i=sb.lastIndexOf("and"))!=-1){
  60. criteriaString=sb.substring(0,i);
  61. }
  62. returncriteriaString;
  63. }
  64. //将Criteria各条件的值转换为List<Object>
  65. publicstaticList<Object>getCriteriaValues(List<Criterion>criteria){
  66. List<Object>criteriaValues=criteria.isEmpty()?Collections
  67. .emptyList():newArrayList<Object>();
  68. for(Criterioncriterion:criteria){
  69. criteriaValues.add(criterion.getValue());
  70. }
  71. returncriteriaValues;
  72. }
  73. publicCriterionTypegetCriterionType(){
  74. returncriterionType;
  75. }
  76. publicvoidsetCriterionType(CriterionTypecriterionType){
  77. this.criterionType=criterionType;
  78. }
  79. publicStringgetField(){
  80. returnfield;
  81. }
  82. publicvoidsetField(Stringfield){
  83. this.field=field;
  84. }
  85. publicObjectgetValue(){
  86. returnvalue;
  87. }
  88. publicvoidsetValue(Objectvalue){
  89. this.value=value;
  90. }
  91. publicstaticCriteriongetCompareCriterion(CompareTypecompareType,
  92. Stringfield,Objectvalue,StringtableName){
  93. CompareCriterioncompareCriterion=newCompareCriterion();
  94. compareCriterion.setCriterionType(CriterionType.COMPARE);
  95. compareCriterion.setCompareType(compareType);
  96. compareCriterion.setField(field);
  97. compareCriterion.setValue(value);
  98. compareCriterion.setTableName(tableName);
  99. returncompareCriterion;
  100. }
  101. publicstaticCriteriongetLikeCriterion(Stringfield,Objectvalue,
  102. StringtableName){
  103. LikeCriterionlikeCriterion=newLikeCriterion();
  104. likeCriterion.setCriterionType(CriterionType.LIKE);
  105. likeCriterion.setField(field);
  106. likeCriterion.setValue(value);
  107. likeCriterion.setTableName(tableName);
  108. returnlikeCriterion;
  109. }
  110. publicstaticCriteriongetNotLikeCriterion(Stringfield,Objectvalue,
  111. StringtableName){
  112. NotLikeCriterionnotLikeCriterion=newNotLikeCriterion();
  113. notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE);
  114. notLikeCriterion.setField(field);
  115. notLikeCriterion.setValue(value);
  116. notLikeCriterion.setTableName(tableName);
  117. returnnotLikeCriterion;
  118. }
  119. publicstaticCriteriongetEqualCriterion(Stringfield,Objectvalue,
  120. StringtableName){
  121. EqualCriterionequalCriterion=newEqualCriterion();
  122. equalCriterion.setCriterionType(CriterionType.EQUAL);
  123. equalCriterion.setField(field);
  124. equalCriterion.setValue(value);
  125. equalCriterion.setTableName(tableName);
  126. returnequalCriterion;
  127. }
  128. publicstaticclassLikeCriterionextendsCriterion{
  129. }
  130. publicstaticclassNotLikeCriterionextendsCriterion{
  131. }
  132. publicstaticclassEqualCriterionextendsCriterion{
  133. }
  134. publicstaticclassCompareCriterionextendsCriterion{
  135. privateCompareTypecompareType;
  136. publicCompareTypegetCompareType(){
  137. returncompareType;
  138. }
  139. publicvoidsetCompareType(CompareTypecompareType){
  140. this.compareType=compareType;
  141. }
  142. }
  143. publicStringgetTableName(){
  144. returntableName;
  145. }
  146. publicvoidsetTableName(StringtableName){
  147. this.tableName=tableName;
  148. }
  149. publicStringgetFieldPrefix(){
  150. return(tableName==null||tableName.length()==0)?"":tableName
  151. +".";
  152. }
  153. }

简要说明一下:

  • 我把Criterion分成4类:EqualCriterion、CompareCriterion、LikeCriterion、NotLikeCriterion。(具体划分方式全为使用方便)
  • 另外还有两个静态方法:convertToSql和getCriteriaValues,用来将Criterion列表转化为JdbcTemplate需要的SQL子句和参数列表。


回到ListContactsAction,代码如下:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.Collections;
  3. importjava.util.List;
  4. importcom.byzl.hare.dao.impl.Criterion;
  5. importcom.byzl.hare.model.Contact;
  6. importcom.byzl.hare.service.ContactService;
  7. @SuppressWarnings("serial")
  8. publicclassListContactsActionextendsJqGridBaseAction<Contact>{
  9. privateContactServicecontactService;
  10. @Override
  11. publicStringexecute(){
  12. returnthis.refreshGridModel();
  13. }
  14. @Override
  15. publicintgetResultSize(){
  16. returnthis.contactService.queryResultsCount(null);
  17. }
  18. @Override
  19. publicList<Contact>listResults(intfrom,intlength){
  20. returnthis.contactService.queryByPage(null,from,length);
  21. }
  22. @Override
  23. publicintgetResultSize(List<Criterion>criteria){
  24. returnthis.contactService.queryResultsCount(criteria);
  25. }
  26. @Override
  27. publicList<Contact>listResults(List<Criterion>criteria,intfrom,intlength){
  28. List<Contact>results=Collections.emptyList();
  29. results=this.contactService.queryByPage(criteria,from,length);
  30. returnresults;
  31. }
  32. publicvoidsetContactService(ContactServicecontactService){
  33. this.contactService=contactService;
  34. }
  35. }

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 plaincopyprint?
  1. varsingleCriterionSearch=function(){
  2. $("#gridTable").jqGrid("searchGrid",{
  3. caption:"查找",
  4. Find:"Go!",
  5. closeAfterSearch:true
  6. });
  7. };

等同于

[javascript] view plaincopyprint?
  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 plaincopyprint?
  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 plaincopyprint?
  1. varcomplexCriteriaSearch=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 plaincopyprint?
  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 plaincopyprint?
  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列表。

  1. publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
  2. List<Criterion>criteria=newArrayList<Criterion>();
  3. JSONObjectjsonObject=JSONObject.fromObject(filters);
  4. JSONArrayrules=jsonObject.getJSONArray("rules");
  5. for(Objectobj:rules){
  6. JSONObjectrule=(JSONObject)obj;
  7. Stringfield=rule.getString("field");
  8. Stringop=rule.getString("op");
  9. Stringdata=rule.getString("data");
  10. Criterioncriterion=this.generateSearchCriterion(field,data,op);
  11. if(criterion!=null){
  12. criteria.add(criterion);
  13. }
  14. }
  15. returncriteria;
  16. }

其余部分的代码:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. importnet.sf.json.JSONArray;
  6. importnet.sf.json.JSONObject;
  7. importcom.byzl.hare.dao.impl.Criterion;
  8. importcom.byzl.hare.dao.impl.Criterion.CompareType;
  9. importcom.opensymphony.xwork2.ActionSupport;
  10. @SuppressWarnings("serial")
  11. publicabstractclassJqGridBaseAction<T>extendsActionSupport{
  12. privateList<T>gridModel=Collections.emptyList();
  13. privateIntegerrows=0;
  14. privateIntegerpage=0;
  15. privateIntegertotal=0;
  16. privateIntegerrecord=0;
  17. privateStringsord;
  18. privateStringsidx;
  19. privatebooleansearch;
  20. privateStringsearchField;
  21. privateStringsearchString;
  22. privateStringsearchOper;
  23. publicabstractintgetResultSize();
  24. publicabstractList<T>listResults(intfrom,intlength);
  25. //(1)添加filters成员变量
  26. privateStringfilters;
  27. publicabstractintgetResultSize(List<Criterion>criteria);
  28. publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
  29. publicStringrefreshGridModel(){
  30. try{
  31. List<Criterion>criteria=Collections.emptyList();
  32. if(search==true){
  33. criteria=newArrayList<Criterion>();
  34. //(2)将Filter转化为Criterion列表,并加入总的Criterion列表
  35. if(filters!=null&&filters.length()>0){
  36. criteria.addAll(this.generateSearchCriteriaFromFilters(filters));
  37. }
  38. //(3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表
  39. Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
  40. if(criterion!=null){
  41. criteria.add(criterion);
  42. }
  43. }
  44. intfrom=rows*(page-1);
  45. intlength=rows;
  46. List<T>results=Collections.emptyList();
  47. if(!criteria.isEmpty()){
  48. record=this.getResultSize(criteria);
  49. results=this.listResults(criteria,from,length);
  50. }else{
  51. record=this.getResultSize();
  52. results=this.listResults(from,length);
  53. }
  54. this.setGridModel(results);
  55. total=(int)Math.ceil((double)record/(double)rows);
  56. returnSUCCESS;
  57. }catch(Exceptione){
  58. e.printStackTrace();
  59. this.addActionError(e.getMessage());
  60. returnERROR;
  61. }
  62. }
  63. publicCriteriongenerateSearchCriterion(StringsearchField,
  64. StringsearchString,StringsearchOper){
  65. ...
  66. }
  67. publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
  68. List<Criterion>criteria=newArrayList<Criterion>();
  69. JSONObjectjsonObject=JSONObject.fromObject(filters);
  70. JSONArrayrules=jsonObject.getJSONArray("rules");
  71. for(Objectobj:rules){
  72. JSONObjectrule=(JSONObject)obj;
  73. Stringfield=rule.getString("field");
  74. Stringop=rule.getString("op");
  75. Stringdata=rule.getString("data");
  76. Criterioncriterion=this.generateSearchCriterion(field,data,op);
  77. if(criterion!=null){
  78. criteria.add(criterion);
  79. }
  80. }
  81. returncriteria;
  82. }
  83. //getter和setter
  84. ...
  85. }

经过如上修改,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 plaincopyprint?
  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 plaincopyprint?
  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();

这篇主要讲的是jqGrid的查找功能。

根据官方文档的介绍,jqGrid的查找功能分四种:

  • 工具条查询;
  • 自定义查询;
  • 单条件表单查询;
  • 高级表单查询(复杂条件查询);


我个人认为这样划分比较复杂,可以基本分为两大类,即:
表单查询:包括单条件查询和高级查询(复杂条件查询);
工具条查询:包括工具条查询和自定义查询;

而这两大类中,也以表单查询更常用。

现在逐个说明一下(我改变了官方文档的讲解顺序,我觉得自己的这个顺序,更直观,更靠近现实使用)。


1. 单条件表单查询

先从服务器端看起,为了配合jqGrid的查询功能,我们需要在JqGridBaseAction类中添加几个成员变量。成员变量的名字必须和jqGrid的prmNames选项中定义的参数名相对应上(具体参考本系列文章的第一篇)。

改进后的JqGridBaseAction类代码:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. importcom.byzl.hare.dao.impl.Criterion;
  6. importcom.byzl.hare.dao.impl.Criterion.CompareType;
  7. importcom.opensymphony.xwork2.ActionSupport;
  8. @SuppressWarnings("serial")
  9. publicabstractclassJqGridBaseAction<T>extendsActionSupport{
  10. privateList<T>gridModel=Collections.emptyList();
  11. privateIntegerrows=0;
  12. privateIntegerpage=0;
  13. privateIntegertotal=0;
  14. privateIntegerrecord=0;
  15. privateStringsord;
  16. privateStringsidx;
  17. //(1)添加和查询有关的成员变量search、searchField、searchString、searchOper
  18. privatebooleansearch;
  19. privateStringsearchField;
  20. privateStringsearchString;
  21. privateStringsearchOper;
  22. publicabstractintgetResultSize();
  23. publicabstractList<T>listResults(intfrom,intlength);
  24. //(2)添加用于根据条件进行查询的方法
  25. publicabstractintgetResultSize(List<Criterion>criteria);
  26. publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
  27. publicStringrefreshGridModel(){
  28. try{
  29. List<Criterion>criteria=Collections.emptyList();
  30. //(3)如果search值为true,则表明是查询请求
  31. if(search==true){
  32. //(4)通过searchField、searchString、searchOper生成通用的查询条件
  33. Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
  34. criteria=newArrayList<Criterion>();
  35. if(criterion!=null){
  36. criteria.add(criterion);
  37. }
  38. }
  39. intfrom=rows*(page-1);
  40. intlength=rows;
  41. List<T>results=Collections.emptyList();
  42. if(!criteria.isEmpty()){//(5)如果criteria列表不为空,则根据条件进行查询
  43. record=this.getResultSize(criteria);
  44. results=this.listResults(criteria,from,length);
  45. }else{
  46. record=this.getResultSize();
  47. results=this.listResults(from,length);
  48. }
  49. this.setGridModel(results);
  50. total=(int)Math.ceil((double)record/(double)rows);
  51. returnSUCCESS;
  52. }catch(Exceptione){
  53. e.printStackTrace();
  54. this.addActionError(e.getMessage());
  55. returnERROR;
  56. }
  57. }
  58. //(6)通过searchField、searchString、searchOper三个参数生成Criterion的方法
  59. publicCriteriongenerateSearchCriterion(StringsearchField,
  60. StringsearchString,StringsearchOper){
  61. Criterioncriterion=null;
  62. //(7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion
  63. if(searchField!=null&&searchString!=null
  64. &searchString.length()>0&&searchOper!=null){
  65. if("eq".equals(searchOper)){
  66. criterion=Criterion.getEqualCriterion(searchField,
  67. searchString,null);
  68. }elseif("ne".equals(searchOper)){
  69. criterion=Criterion.getCompareCriterion(CompareType.NE,
  70. searchField,searchString,null);
  71. }elseif("lt".equals(searchOper)){
  72. criterion=Criterion.getCompareCriterion(CompareType.LT,
  73. searchField,searchString,null);
  74. }elseif("le".equals(searchOper)){
  75. criterion=Criterion.getCompareCriterion(CompareType.LTE,
  76. searchField,searchString,null);
  77. }elseif("gt".equals(searchOper)){
  78. criterion=Criterion.getCompareCriterion(CompareType.GT,
  79. searchField,searchString,null);
  80. }elseif("ge".equals(searchOper)){
  81. criterion=Criterion.getCompareCriterion(CompareType.GTE,
  82. searchField,searchString,null);
  83. }elseif("bw".equals(searchOper)){
  84. criterion=Criterion.getLikeCriterion(searchField,
  85. searchString+"%",null);
  86. }elseif("bn".equals(searchOper)){
  87. criterion=Criterion.getNotLikeCriterion(searchField,
  88. searchString+"%",null);
  89. }elseif("ew".equals(searchOper)){
  90. criterion=Criterion.getLikeCriterion(searchField,"%"
  91. +searchString,null);
  92. }elseif("en".equals(searchOper)){
  93. criterion=Criterion.getNotLikeCriterion(searchField,"%"
  94. +searchString,null);
  95. }elseif("cn".equals(searchOper)){
  96. criterion=Criterion.getLikeCriterion(searchField,"%"
  97. +searchString+"%",null);
  98. }elseif("nc".equals(searchOper)){
  99. criterion=Criterion.getNotLikeCriterion(searchField,"%"
  100. +searchString+"%",null);
  101. }
  102. }
  103. returncriterion;
  104. }
  105. //getter和setter
  106. ...
  107. }

说明:

  • (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类的代码:

  1. packagecom.byzl.hare.dao.impl;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. publicclassCriterion{
  6. publicstaticenumCriterionType{
  7. EQUAL,LIKE,COMPARE,NOT_LIKE
  8. }
  9. publicstaticenumCompareType{
  10. GT,GTE,LT,LTE,EQ,NE
  11. }
  12. privateCriterionTypecriterionType;
  13. privateStringtableName;
  14. privateStringfield;
  15. privateObjectvalue;
  16. //将Criteria转换为SQL条件语句
  17. publicstaticStringconvertToSql(List<Criterion>criteria){
  18. StringcriteriaString="";
  19. StringBuildersb=newStringBuilder();
  20. for(Criterioncriterion:criteria){
  21. Stringprefix=criterion.getFieldPrefix();
  22. switch(criterion.getCriterionType()){
  23. caseEQUAL:
  24. sb.append(prefix+criterion.getField()+"=?and");
  25. break;
  26. caseLIKE:
  27. sb.append(prefix+criterion.getField()+"like?and");
  28. break;
  29. caseNOT_LIKE:
  30. sb.append(prefix+criterion.getField()+"notlike?and");
  31. break;
  32. caseCOMPARE:
  33. CompareTypecompareType=((CompareCriterion)criterion)
  34. .getCompareType();
  35. switch(compareType){
  36. caseEQ:
  37. sb.append(prefix+criterion.getField()+"=?and");
  38. break;
  39. caseNE:
  40. sb.append(prefix+criterion.getField()+"<>?and");
  41. break;
  42. caseGT:
  43. sb.append(prefix+criterion.getField()+">?and");
  44. break;
  45. caseGTE:
  46. sb.append(prefix+criterion.getField()+">=?and");
  47. break;
  48. caseLT:
  49. sb.append(prefix+criterion.getField()+"<?and");
  50. break;
  51. caseLTE:
  52. sb.append(prefix+criterion.getField()+"<=?and");
  53. break;
  54. }
  55. break;
  56. }
  57. }
  58. inti=-1;
  59. if((i=sb.lastIndexOf("and"))!=-1){
  60. criteriaString=sb.substring(0,i);
  61. }
  62. returncriteriaString;
  63. }
  64. //将Criteria各条件的值转换为List<Object>
  65. publicstaticList<Object>getCriteriaValues(List<Criterion>criteria){
  66. List<Object>criteriaValues=criteria.isEmpty()?Collections
  67. .emptyList():newArrayList<Object>();
  68. for(Criterioncriterion:criteria){
  69. criteriaValues.add(criterion.getValue());
  70. }
  71. returncriteriaValues;
  72. }
  73. publicCriterionTypegetCriterionType(){
  74. returncriterionType;
  75. }
  76. publicvoidsetCriterionType(CriterionTypecriterionType){
  77. this.criterionType=criterionType;
  78. }
  79. publicStringgetField(){
  80. returnfield;
  81. }
  82. publicvoidsetField(Stringfield){
  83. this.field=field;
  84. }
  85. publicObjectgetValue(){
  86. returnvalue;
  87. }
  88. publicvoidsetValue(Objectvalue){
  89. this.value=value;
  90. }
  91. publicstaticCriteriongetCompareCriterion(CompareTypecompareType,
  92. Stringfield,Objectvalue,StringtableName){
  93. CompareCriterioncompareCriterion=newCompareCriterion();
  94. compareCriterion.setCriterionType(CriterionType.COMPARE);
  95. compareCriterion.setCompareType(compareType);
  96. compareCriterion.setField(field);
  97. compareCriterion.setValue(value);
  98. compareCriterion.setTableName(tableName);
  99. returncompareCriterion;
  100. }
  101. publicstaticCriteriongetLikeCriterion(Stringfield,Objectvalue,
  102. StringtableName){
  103. LikeCriterionlikeCriterion=newLikeCriterion();
  104. likeCriterion.setCriterionType(CriterionType.LIKE);
  105. likeCriterion.setField(field);
  106. likeCriterion.setValue(value);
  107. likeCriterion.setTableName(tableName);
  108. returnlikeCriterion;
  109. }
  110. publicstaticCriteriongetNotLikeCriterion(Stringfield,Objectvalue,
  111. StringtableName){
  112. NotLikeCriterionnotLikeCriterion=newNotLikeCriterion();
  113. notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE);
  114. notLikeCriterion.setField(field);
  115. notLikeCriterion.setValue(value);
  116. notLikeCriterion.setTableName(tableName);
  117. returnnotLikeCriterion;
  118. }
  119. publicstaticCriteriongetEqualCriterion(Stringfield,Objectvalue,
  120. StringtableName){
  121. EqualCriterionequalCriterion=newEqualCriterion();
  122. equalCriterion.setCriterionType(CriterionType.EQUAL);
  123. equalCriterion.setField(field);
  124. equalCriterion.setValue(value);
  125. equalCriterion.setTableName(tableName);
  126. returnequalCriterion;
  127. }
  128. publicstaticclassLikeCriterionextendsCriterion{
  129. }
  130. publicstaticclassNotLikeCriterionextendsCriterion{
  131. }
  132. publicstaticclassEqualCriterionextendsCriterion{
  133. }
  134. publicstaticclassCompareCriterionextendsCriterion{
  135. privateCompareTypecompareType;
  136. publicCompareTypegetCompareType(){
  137. returncompareType;
  138. }
  139. publicvoidsetCompareType(CompareTypecompareType){
  140. this.compareType=compareType;
  141. }
  142. }
  143. publicStringgetTableName(){
  144. returntableName;
  145. }
  146. publicvoidsetTableName(StringtableName){
  147. this.tableName=tableName;
  148. }
  149. publicStringgetFieldPrefix(){
  150. return(tableName==null||tableName.length()==0)?"":tableName
  151. +".";
  152. }
  153. }

简要说明一下:

  • 我把Criterion分成4类:EqualCriterion、CompareCriterion、LikeCriterion、NotLikeCriterion。(具体划分方式全为使用方便)
  • 另外还有两个静态方法:convertToSql和getCriteriaValues,用来将Criterion列表转化为JdbcTemplate需要的SQL子句和参数列表。


回到ListContactsAction,代码如下:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.Collections;
  3. importjava.util.List;
  4. importcom.byzl.hare.dao.impl.Criterion;
  5. importcom.byzl.hare.model.Contact;
  6. importcom.byzl.hare.service.ContactService;
  7. @SuppressWarnings("serial")
  8. publicclassListContactsActionextendsJqGridBaseAction<Contact>{
  9. privateContactServicecontactService;
  10. @Override
  11. publicStringexecute(){
  12. returnthis.refreshGridModel();
  13. }
  14. @Override
  15. publicintgetResultSize(){
  16. returnthis.contactService.queryResultsCount(null);
  17. }
  18. @Override
  19. publicList<Contact>listResults(intfrom,intlength){
  20. returnthis.contactService.queryByPage(null,from,length);
  21. }
  22. @Override
  23. publicintgetResultSize(List<Criterion>criteria){
  24. returnthis.contactService.queryResultsCount(criteria);
  25. }
  26. @Override
  27. publicList<Contact>listResults(List<Criterion>criteria,intfrom,intlength){
  28. List<Contact>results=Collections.emptyList();
  29. results=this.contactService.queryByPage(criteria,from,length);
  30. returnresults;
  31. }
  32. publicvoidsetContactService(ContactServicecontactService){
  33. this.contactService=contactService;
  34. }
  35. }

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 plaincopyprint?
  1. varsingleCriterionSearch=function(){
  2. $("#gridTable").jqGrid("searchGrid",{
  3. caption:"查找",
  4. Find:"Go!",
  5. closeAfterSearch:true
  6. });
  7. };

等同于

[javascript] view plaincopyprint?
  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 plaincopyprint?
  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 plaincopyprint?
  1. varcomplexCriteriaSearch=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 plaincopyprint?
  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 plaincopyprint?
  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列表。

  1. publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
  2. List<Criterion>criteria=newArrayList<Criterion>();
  3. JSONObjectjsonObject=JSONObject.fromObject(filters);
  4. JSONArrayrules=jsonObject.getJSONArray("rules");
  5. for(Objectobj:rules){
  6. JSONObjectrule=(JSONObject)obj;
  7. Stringfield=rule.getString("field");
  8. Stringop=rule.getString("op");
  9. Stringdata=rule.getString("data");
  10. Criterioncriterion=this.generateSearchCriterion(field,data,op);
  11. if(criterion!=null){
  12. criteria.add(criterion);
  13. }
  14. }
  15. returncriteria;
  16. }

其余部分的代码:

  1. packagecn.gengv.struts2ex.jqGrid;
  2. importjava.util.ArrayList;
  3. importjava.util.Collections;
  4. importjava.util.List;
  5. importnet.sf.json.JSONArray;
  6. importnet.sf.json.JSONObject;
  7. importcom.byzl.hare.dao.impl.Criterion;
  8. importcom.byzl.hare.dao.impl.Criterion.CompareType;
  9. importcom.opensymphony.xwork2.ActionSupport;
  10. @SuppressWarnings("serial")
  11. publicabstractclassJqGridBaseAction<T>extendsActionSupport{
  12. privateList<T>gridModel=Collections.emptyList();
  13. privateIntegerrows=0;
  14. privateIntegerpage=0;
  15. privateIntegertotal=0;
  16. privateIntegerrecord=0;
  17. privateStringsord;
  18. privateStringsidx;
  19. privatebooleansearch;
  20. privateStringsearchField;
  21. privateStringsearchString;
  22. privateStringsearchOper;
  23. publicabstractintgetResultSize();
  24. publicabstractList<T>listResults(intfrom,intlength);
  25. //(1)添加filters成员变量
  26. privateStringfilters;
  27. publicabstractintgetResultSize(List<Criterion>criteria);
  28. publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
  29. publicStringrefreshGridModel(){
  30. try{
  31. List<Criterion>criteria=Collections.emptyList();
  32. if(search==true){
  33. criteria=newArrayList<Criterion>();
  34. //(2)将Filter转化为Criterion列表,并加入总的Criterion列表
  35. if(filters!=null&&filters.length()>0){
  36. criteria.addAll(this.generateSearchCriteriaFromFilters(filters));
  37. }
  38. //(3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表
  39. Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
  40. if(criterion!=null){
  41. criteria.add(criterion);
  42. }
  43. }
  44. intfrom=rows*(page-1);
  45. intlength=rows;
  46. List<T>results=Collections.emptyList();
  47. if(!criteria.isEmpty()){
  48. record=this.getResultSize(criteria);
  49. results=this.listResults(criteria,from,length);
  50. }else{
  51. record=this.getResultSize();
  52. results=this.listResults(from,length);
  53. }
  54. this.setGridModel(results);
  55. total=(int)Math.ceil((double)record/(double)rows);
  56. returnSUCCESS;
  57. }catch(Exceptione){
  58. e.printStackTrace();
  59. this.addActionError(e.getMessage());
  60. returnERROR;
  61. }
  62. }
  63. publicCriteriongenerateSearchCriterion(StringsearchField,
  64. StringsearchString,StringsearchOper){
  65. ...
  66. }
  67. publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
  68. List<Criterion>criteria=newArrayList<Criterion>();
  69. JSONObjectjsonObject=JSONObject.fromObject(filters);
  70. JSONArrayrules=jsonObject.getJSONArray("rules");
  71. for(Objectobj:rules){
  72. JSONObjectrule=(JSONObject)obj;
  73. Stringfield=rule.getString("field");
  74. Stringop=rule.getString("op");
  75. Stringdata=rule.getString("data");
  76. Criterioncriterion=this.generateSearchCriterion(field,data,op);
  77. if(criterion!=null){
  78. criteria.add(criterion);
  79. }
  80. }
  81. returncriteria;
  82. }
  83. //getter和setter
  84. ...
  85. }

经过如上修改,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 plaincopyprint?
  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 plaincopyprint?
  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();

分享到:
评论

相关推荐

    jqGrid与Struts2的结合应用_操作Grid数据

    总结来说,jqGrid 与 Struts2 的结合应用提供了高效的数据展示和管理能力。通过理解并熟练运用 jqGrid 的核心方法,开发者可以构建出功能丰富的数据网格,同时结合 Struts2 的灵活性,实现前后端的无缝协作,提高...

    jqGrid与Struts2的结合应用

    通过jqGrid与Struts2的结合,我们可以构建出具有强大数据管理功能的Web应用,提供用户友好的界面和高效的后台处理能力。这种结合方式在企业级项目中非常常见,能够满足复杂的数据展示和操作需求。

    jqgrid+struts2

    6. **前端与后端数据交互**:jqGrid通过AJAX请求向Struts2 Action发送请求,Action根据请求参数进行相应的数据处理,然后将结果返回给前端,更新表格内容。 **四、示例代码片段** 以下是一个简单的jqGrid初始化示例...

    jqgrid+struts2实现的增删改查

    在本项目中,jqGrid 与 Struts2 结合,实现了Web应用中的核心功能——增删改查。以下是关键步骤: 1. **配置 Struts2**:首先,需要在项目的 `struts.xml` 配置文件中设置Action类及其对应的URL映射,以及指定使用...

    jqGrid与Struts2 详细文档

    在 Struts2 中,你可以创建一个 Action 来处理 jqGrid 的请求,将请求参数映射到 Action 类的属性,然后执行相应的数据库查询或操作。Action 返回的结果可以是 JSON 格式,方便 jqGrid 解析。 总的来说,jqGrid 与...

    jqGrid表格应用——新增与删除数据

    在"jqGrid表格应用——新增与删除数据"这个主题中,我们可以探讨以下知识点: 1. **jqGrid的基本结构**:jqGrid的HTML结构通常包括一个`&lt;table&gt;`元素,以及必要的CSS和JavaScript引用。例如,`index.html`可能包含`...

    jqGrid与Sturts2的结合例子

    将jqGrid与Struts2结合,可以创建高效的前端数据展示和交互界面,同时利用Struts2的强大后端处理能力。 在这个"jqGrid与Struts2的结合例子"中,我们将探讨如何将这两者集成,以实现动态加载、数据过滤、编辑和保存...

    jqgrid+struts2+ibatis增删改查

    在IT领域,尤其是在Web开发中,"jqGrid+Struts2+iBatis+Oracle"是一种常见的技术组合,用于构建功能强大的数据管理应用。这里,jqGrid是一个强大的JavaScript表格插件,Struts2是一个Java Web应用程序框架,iBatis是...

    jqGrid demo in JSP Struts2 & Hibernate 新版myeclise for Spring 10.0

    struts配置文件和hibernate的配置文件都在src目录下 4.这就是jqGrid最简单的演示,没有加入任何其它功能, Good Luck! 有人问到没有spring,由于主要是演示jqGrid和jQuery的AJAX功能,所以没有加上spring框架, 如有...

    jqGrid 中文大全(1)

    jqGrid尤其在Web应用程序中,与后端如Struts2等框架结合使用时,能够提供高效的数据展示和管理。 在“jqGrid中文大全(1)”这个压缩包中,包含了一系列关于jqGrid的中文教程和文档,这些资料可以帮助开发者更深入地...

    Struts2JQGrid java版本分页

    Struts2JQGrid是一个基于Java的Web开发框架,它结合了Struts2和JQGrid两个强大的工具,用于创建动态、交互式的网格数据展示和管理界面。在本项目中,Struts2作为MVC(Model-View-Controller)框架负责处理业务逻辑和...

    jqGrid demo in Struts2 & Hibernate war file part 1

    Struts2 和 hibernate 演示 jqGrid, 使用Action中的 代码可以容易的把jqGrid 用于servlet或纯jsp. Struts 2.16, jqGrid 3.5b, hibernate 3.2 annotation 由于我的上传权限为20M,而我上传上的包括所有的源代码和支持...

    jqGrid增删改查例子

    1. 动态Action配置:Struts2的Action类可以动态响应来自jqGrid的不同请求,比如获取数据、保存数据等。 2. 数据绑定:使用Struts2的ValueStack和OGNL(Object-Graph Navigation Language)进行数据绑定,方便地将...

    jqgrid+三大框架

    【jqgrid+三大框架】是将前端数据展示组件jqGrid与经典的Java后端开发框架——Hibernate、Struts和Spring相结合的应用实例。这个项目基于MyEclipse2014开发环境,主要目标是实现数据的查询功能并通过jqGrid进行前端...

    JqGrid Demo json

    在这个Demo中,我们将深入探讨JqGrid与JSON的结合以及Struts2框架如何在后台提供数据支持。 首先,JqGrid允许用户通过Ajax方式获取和操作数据,提供了排序、分页、搜索和编辑等功能。在`JqGrid Demo json`中,JSON...

    关于jqGrid中查询功能

    首先,jqGrid内置了查询插件,允许用户通过前端界面进行数据筛选。当用户触发查询操作时,jqGrid会以POST方式向服务器发送请求,携带两个关键参数:“_search”和“filters”。其中,“_search”的值为“true”表明...

    jqGrid demo in Struts2 & Hibernate war file part2

    jqGrid demo in Struts2 & Hibernate war file part2

    jqgrid加载本地数据并且分页例子

    通过这个示例,你可以了解到如何将本地数据与jqGrid结合,实现动态分页和排序,从而为用户提供更友好的数据浏览体验。在实际项目中,你可能需要根据具体需求调整jqGrid的配置,如添加自定义列处理函数,实现更复杂的...

    jqGrid详解及高级应用

    2. 通过XML字符串数据获取:与XML数据类似,不过是将数据以字符串形式直接传递给jqGrid进行处理。 3. 通过JSON数据获取:后端返回JSON格式的数据,jqGrid通过配置jsonReader来解析。 4. 通过JSON字符串数据获取:...

    ssh+jqgrid的整合

    2. **创建Action**:在Struts2中,你需要创建一个Action类,该类将负责处理来自JQGrid的请求。这些请求通常包含对数据进行增删改查的操作。Action类需要继承自Struts2的ActionSupport,并实现相应的业务逻辑方法。 ...

Global site tag (gtag.js) - Google Analytics