这篇主要讲的是jqGrid的查找功能。
根据官方文档的介绍,jqGrid的查找功能分四种:
- 工具条查询;
- 自定义查询;
- 单条件表单查询;
- 高级表单查询(复杂条件查询);
我个人认为这样划分比较复杂,可以基本分为两大类,即:
表单查询:包括单条件查询和高级查询(复杂条件查询);
工具条查询:包括工具条查询和自定义查询;
而这两大类中,也以表单查询更常用。
现在逐个说明一下(我改变了官方文档的讲解顺序,我觉得自己的这个顺序,更直观,更靠近现实使用)。
1. 单条件表单查询
先从服务器端看起,为了配合jqGrid的查询功能,我们需要在JqGridBaseAction类中添加几个成员变量。成员变量的名字必须和jqGrid的prmNames选项中定义的参数名相对应上(具体参考本系列文章的第一篇)。
改进后的JqGridBaseAction类代码:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.dao.impl.Criterion.CompareType;
- importcom.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings("serial")
- publicabstractclassJqGridBaseAction<T>extendsActionSupport{
- privateList<T>gridModel=Collections.emptyList();
- privateIntegerrows=0;
- privateIntegerpage=0;
- privateIntegertotal=0;
- privateIntegerrecord=0;
- privateStringsord;
- privateStringsidx;
- //(1)添加和查询有关的成员变量search、searchField、searchString、searchOper
- privatebooleansearch;
- privateStringsearchField;
- privateStringsearchString;
- privateStringsearchOper;
- publicabstractintgetResultSize();
- publicabstractList<T>listResults(intfrom,intlength);
- //(2)添加用于根据条件进行查询的方法
- publicabstractintgetResultSize(List<Criterion>criteria);
- publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
- publicStringrefreshGridModel(){
- try{
- List<Criterion>criteria=Collections.emptyList();
- //(3)如果search值为true,则表明是查询请求
- if(search==true){
- //(4)通过searchField、searchString、searchOper生成通用的查询条件
- Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
- criteria=newArrayList<Criterion>();
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- intfrom=rows*(page-1);
- intlength=rows;
- List<T>results=Collections.emptyList();
- if(!criteria.isEmpty()){//(5)如果criteria列表不为空,则根据条件进行查询
- record=this.getResultSize(criteria);
- results=this.listResults(criteria,from,length);
- }else{
- record=this.getResultSize();
- results=this.listResults(from,length);
- }
- this.setGridModel(results);
- total=(int)Math.ceil((double)record/(double)rows);
- returnSUCCESS;
- }catch(Exceptione){
- e.printStackTrace();
- this.addActionError(e.getMessage());
- returnERROR;
- }
- }
- //(6)通过searchField、searchString、searchOper三个参数生成Criterion的方法
- publicCriteriongenerateSearchCriterion(StringsearchField,
- StringsearchString,StringsearchOper){
- Criterioncriterion=null;
- //(7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion
- if(searchField!=null&&searchString!=null
- &searchString.length()>0&&searchOper!=null){
- if("eq".equals(searchOper)){
- criterion=Criterion.getEqualCriterion(searchField,
- searchString,null);
- }elseif("ne".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.NE,
- searchField,searchString,null);
- }elseif("lt".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.LT,
- searchField,searchString,null);
- }elseif("le".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.LTE,
- searchField,searchString,null);
- }elseif("gt".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.GT,
- searchField,searchString,null);
- }elseif("ge".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.GTE,
- searchField,searchString,null);
- }elseif("bw".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,
- searchString+"%",null);
- }elseif("bn".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,
- searchString+"%",null);
- }elseif("ew".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,"%"
- +searchString,null);
- }elseif("en".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,"%"
- +searchString,null);
- }elseif("cn".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,"%"
- +searchString+"%",null);
- }elseif("nc".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,"%"
- +searchString+"%",null);
- }
- }
- returncriterion;
- }
- //getter和setter
- ...
- }
package cn.gengv.struts2ex.jqGrid; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.dao.impl.Criterion.CompareType; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public abstract class JqGridBaseAction<T> extends ActionSupport { private List<T> gridModel = Collections.emptyList(); private Integer rows = 0; private Integer page = 0; private Integer total = 0; private Integer record = 0; private String sord; private String sidx; // (1)添加和查询有关的成员变量search、searchField、searchString、searchOper private boolean search; private String searchField; private String searchString; private String searchOper; public abstract int getResultSize(); public abstract List<T> listResults(int from, int length); // (2)添加用于根据条件进行查询的方法 public abstract int getResultSize(List<Criterion> criteria); public abstract List<T> listResults(List<Criterion> criteria, int from, int length); public String refreshGridModel() { try { List<Criterion> criteria = Collections.emptyList(); // (3)如果search值为true,则表明是查询请求 if(search == true) { // (4)通过searchField、searchString、searchOper生成通用的查询条件 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper); criteria = new ArrayList<Criterion>(); if(criterion != null) { criteria.add(criterion); } } int from = rows * (page - 1); int length = rows; List<T> results = Collections.emptyList(); if(!criteria.isEmpty()) { // (5)如果criteria列表不为空,则根据条件进行查询 record = this.getResultSize(criteria); results = this.listResults(criteria, from, length); } else { record = this.getResultSize(); results = this.listResults(from, length); } this.setGridModel(results); total = (int) Math.ceil((double) record / (double) rows); return SUCCESS; } catch (Exception e) { e.printStackTrace(); this.addActionError(e.getMessage()); return ERROR; } } // (6)通过searchField、searchString、searchOper三个参数生成Criterion的方法 public Criterion generateSearchCriterion(String searchField, String searchString, String searchOper) { Criterion criterion = null; // (7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion if (searchField != null && searchString != null & searchString.length() > 0 && searchOper != null) { if ("eq".equals(searchOper)) { criterion = Criterion.getEqualCriterion(searchField, searchString, null); } else if ("ne".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.NE, searchField, searchString, null); } else if ("lt".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.LT, searchField, searchString, null); } else if ("le".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.LTE, searchField, searchString, null); } else if ("gt".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.GT, searchField, searchString, null); } else if ("ge".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.GTE, searchField, searchString, null); } else if ("bw".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, searchString + "%", null); } else if ("bn".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, searchString + "%", null); } else if ("ew".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, "%" + searchString, null); } else if ("en".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, "%" + searchString, null); } else if ("cn".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, "%" + searchString + "%", null); } else if ("nc".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, "%" + searchString + "%", null); } } return criterion; } // getter和setter ... }
说明:
- (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类的代码:
- packagecom.byzl.hare.dao.impl;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- publicclassCriterion{
- publicstaticenumCriterionType{
- EQUAL,LIKE,COMPARE,NOT_LIKE
- }
- publicstaticenumCompareType{
- GT,GTE,LT,LTE,EQ,NE
- }
- privateCriterionTypecriterionType;
- privateStringtableName;
- privateStringfield;
- privateObjectvalue;
- //将Criteria转换为SQL条件语句
- publicstaticStringconvertToSql(List<Criterion>criteria){
- StringcriteriaString="";
- StringBuildersb=newStringBuilder();
- for(Criterioncriterion:criteria){
- Stringprefix=criterion.getFieldPrefix();
- switch(criterion.getCriterionType()){
- caseEQUAL:
- sb.append(prefix+criterion.getField()+"=?and");
- break;
- caseLIKE:
- sb.append(prefix+criterion.getField()+"like?and");
- break;
- caseNOT_LIKE:
- sb.append(prefix+criterion.getField()+"notlike?and");
- break;
- caseCOMPARE:
- CompareTypecompareType=((CompareCriterion)criterion)
- .getCompareType();
- switch(compareType){
- caseEQ:
- sb.append(prefix+criterion.getField()+"=?and");
- break;
- caseNE:
- sb.append(prefix+criterion.getField()+"<>?and");
- break;
- caseGT:
- sb.append(prefix+criterion.getField()+">?and");
- break;
- caseGTE:
- sb.append(prefix+criterion.getField()+">=?and");
- break;
- caseLT:
- sb.append(prefix+criterion.getField()+"<?and");
- break;
- caseLTE:
- sb.append(prefix+criterion.getField()+"<=?and");
- break;
- }
- break;
- }
- }
- inti=-1;
- if((i=sb.lastIndexOf("and"))!=-1){
- criteriaString=sb.substring(0,i);
- }
- returncriteriaString;
- }
- //将Criteria各条件的值转换为List<Object>
- publicstaticList<Object>getCriteriaValues(List<Criterion>criteria){
- List<Object>criteriaValues=criteria.isEmpty()?Collections
- .emptyList():newArrayList<Object>();
- for(Criterioncriterion:criteria){
- criteriaValues.add(criterion.getValue());
- }
- returncriteriaValues;
- }
- publicCriterionTypegetCriterionType(){
- returncriterionType;
- }
- publicvoidsetCriterionType(CriterionTypecriterionType){
- this.criterionType=criterionType;
- }
- publicStringgetField(){
- returnfield;
- }
- publicvoidsetField(Stringfield){
- this.field=field;
- }
- publicObjectgetValue(){
- returnvalue;
- }
- publicvoidsetValue(Objectvalue){
- this.value=value;
- }
- publicstaticCriteriongetCompareCriterion(CompareTypecompareType,
- Stringfield,Objectvalue,StringtableName){
- CompareCriterioncompareCriterion=newCompareCriterion();
- compareCriterion.setCriterionType(CriterionType.COMPARE);
- compareCriterion.setCompareType(compareType);
- compareCriterion.setField(field);
- compareCriterion.setValue(value);
- compareCriterion.setTableName(tableName);
- returncompareCriterion;
- }
- publicstaticCriteriongetLikeCriterion(Stringfield,Objectvalue,
- StringtableName){
- LikeCriterionlikeCriterion=newLikeCriterion();
- likeCriterion.setCriterionType(CriterionType.LIKE);
- likeCriterion.setField(field);
- likeCriterion.setValue(value);
- likeCriterion.setTableName(tableName);
- returnlikeCriterion;
- }
- publicstaticCriteriongetNotLikeCriterion(Stringfield,Objectvalue,
- StringtableName){
- NotLikeCriterionnotLikeCriterion=newNotLikeCriterion();
- notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE);
- notLikeCriterion.setField(field);
- notLikeCriterion.setValue(value);
- notLikeCriterion.setTableName(tableName);
- returnnotLikeCriterion;
- }
- publicstaticCriteriongetEqualCriterion(Stringfield,Objectvalue,
- StringtableName){
- EqualCriterionequalCriterion=newEqualCriterion();
- equalCriterion.setCriterionType(CriterionType.EQUAL);
- equalCriterion.setField(field);
- equalCriterion.setValue(value);
- equalCriterion.setTableName(tableName);
- returnequalCriterion;
- }
- publicstaticclassLikeCriterionextendsCriterion{
- }
- publicstaticclassNotLikeCriterionextendsCriterion{
- }
- publicstaticclassEqualCriterionextendsCriterion{
- }
- publicstaticclassCompareCriterionextendsCriterion{
- privateCompareTypecompareType;
- publicCompareTypegetCompareType(){
- returncompareType;
- }
- publicvoidsetCompareType(CompareTypecompareType){
- this.compareType=compareType;
- }
- }
- publicStringgetTableName(){
- returntableName;
- }
- publicvoidsetTableName(StringtableName){
- this.tableName=tableName;
- }
- publicStringgetFieldPrefix(){
- return(tableName==null||tableName.length()==0)?"":tableName
- +".";
- }
- }
package com.byzl.hare.dao.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Criterion { public static enum CriterionType { EQUAL, LIKE, COMPARE, NOT_LIKE } public static enum CompareType { GT, GTE, LT, LTE, EQ, NE } private CriterionType criterionType; private String tableName; private String field; private Object value; // 将Criteria转换为SQL条件语句 public static String convertToSql(List<Criterion> criteria) { String criteriaString = ""; StringBuilder sb = new StringBuilder(); for (Criterion criterion : criteria) { String prefix = criterion.getFieldPrefix(); switch (criterion.getCriterionType()) { case EQUAL: sb.append(prefix + criterion.getField() + "=? and "); break; case LIKE: sb.append(prefix + criterion.getField() + " like ? and "); break; case NOT_LIKE: sb.append(prefix + criterion.getField() + " not like ? and "); break; case COMPARE: CompareType compareType = ((CompareCriterion) criterion) .getCompareType(); switch (compareType) { case EQ: sb.append(prefix + criterion.getField() + "=? and "); break; case NE: sb.append(prefix + criterion.getField() + "<>? and "); break; case GT: sb.append(prefix + criterion.getField() + ">? and "); break; case GTE: sb.append(prefix + criterion.getField() + ">=? and "); break; case LT: sb.append(prefix + criterion.getField() + "<? and "); break; case LTE: sb.append(prefix + criterion.getField() + "<=? and "); break; } break; } } int i = -1; if ((i = sb.lastIndexOf(" and ")) != -1) { criteriaString = sb.substring(0, i); } return criteriaString; } // 将Criteria各条件的值转换为List<Object> public static List<Object> getCriteriaValues(List<Criterion> criteria) { List<Object> criteriaValues = criteria.isEmpty() ? Collections .emptyList() : new ArrayList<Object>(); for (Criterion criterion : criteria) { criteriaValues.add(criterion.getValue()); } return criteriaValues; } public CriterionType getCriterionType() { return criterionType; } public void setCriterionType(CriterionType criterionType) { this.criterionType = criterionType; } public String getField() { return field; } public void setField(String field) { this.field = field; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } public static Criterion getCompareCriterion(CompareType compareType, String field, Object value, String tableName) { CompareCriterion compareCriterion = new CompareCriterion(); compareCriterion.setCriterionType(CriterionType.COMPARE); compareCriterion.setCompareType(compareType); compareCriterion.setField(field); compareCriterion.setValue(value); compareCriterion.setTableName(tableName); return compareCriterion; } public static Criterion getLikeCriterion(String field, Object value, String tableName) { LikeCriterion likeCriterion = new LikeCriterion(); likeCriterion.setCriterionType(CriterionType.LIKE); likeCriterion.setField(field); likeCriterion.setValue(value); likeCriterion.setTableName(tableName); return likeCriterion; } public static Criterion getNotLikeCriterion(String field, Object value, String tableName) { NotLikeCriterion notLikeCriterion = new NotLikeCriterion(); notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE); notLikeCriterion.setField(field); notLikeCriterion.setValue(value); notLikeCriterion.setTableName(tableName); return notLikeCriterion; } public static Criterion getEqualCriterion(String field, Object value, String tableName) { EqualCriterion equalCriterion = new EqualCriterion(); equalCriterion.setCriterionType(CriterionType.EQUAL); equalCriterion.setField(field); equalCriterion.setValue(value); equalCriterion.setTableName(tableName); return equalCriterion; } public static class LikeCriterion extends Criterion { } public static class NotLikeCriterion extends Criterion { } public static class EqualCriterion extends Criterion { } public static class CompareCriterion extends Criterion { private CompareType compareType; public CompareType getCompareType() { return compareType; } public void setCompareType(CompareType compareType) { this.compareType = compareType; } } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public String getFieldPrefix() { return (tableName == null || tableName.length() == 0) ? "" : tableName + "."; } }
简要说明一下:
- 我把Criterion分成4类:EqualCriterion、CompareCriterion、LikeCriterion、NotLikeCriterion。(具体划分方式全为使用方便)
- 另外还有两个静态方法:convertToSql和getCriteriaValues,用来将Criterion列表转化为JdbcTemplate需要的SQL子句和参数列表。
回到ListContactsAction,代码如下:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.Collections;
- importjava.util.List;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.model.Contact;
- importcom.byzl.hare.service.ContactService;
- @SuppressWarnings("serial")
- publicclassListContactsActionextendsJqGridBaseAction<Contact>{
- privateContactServicecontactService;
- @Override
- publicStringexecute(){
- returnthis.refreshGridModel();
- }
- @Override
- publicintgetResultSize(){
- returnthis.contactService.queryResultsCount(null);
- }
- @Override
- publicList<Contact>listResults(intfrom,intlength){
- returnthis.contactService.queryByPage(null,from,length);
- }
- @Override
- publicintgetResultSize(List<Criterion>criteria){
- returnthis.contactService.queryResultsCount(criteria);
- }
- @Override
- publicList<Contact>listResults(List<Criterion>criteria,intfrom,intlength){
- List<Contact>results=Collections.emptyList();
- results=this.contactService.queryByPage(criteria,from,length);
- returnresults;
- }
- publicvoidsetContactService(ContactServicecontactService){
- this.contactService=contactService;
- }
- }
package cn.gengv.struts2ex.jqGrid; import java.util.Collections; import java.util.List; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.model.Contact; import com.byzl.hare.service.ContactService; @SuppressWarnings("serial") public class ListContactsAction extends JqGridBaseAction<Contact> { private ContactService contactService; @Override public String execute() { return this.refreshGridModel(); } @Override public int getResultSize() { return this.contactService.queryResultsCount(null); } @Override public List<Contact> listResults(int from, int length) { return this.contactService.queryByPage(null, from, length); } @Override public int getResultSize(List<Criterion> criteria) { return this.contactService.queryResultsCount(criteria); } @Override public List<Contact> listResults(List<Criterion> criteria, int from, int length) { List<Contact> results = Collections.emptyList(); results = this.contactService.queryByPage(criteria, from, length); return results; } public void setContactService(ContactService contactService) { this.contactService = contactService; } }
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参数中设置这些选项(参见上一篇),作用效果是相同的。
即
- varsingleCriterionSearch=function(){
- $("#gridTable").jqGrid("searchGrid",{
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true
- });
- };
var singleCriterionSearch = function() { $("#gridTable").jqGrid("searchGrid", { caption: "查找", Find: "Go!", closeAfterSearch: true }); };
等同于
- $("#gridTable").jqGrid("navGrid","#gridPager",{},{},{},{},
- {//与查询相关的prmSearch参数
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true
- },{});
$("#gridTable").jqGrid("navGrid", "#gridPager", {},{},{},{}, { // 与查询相关的prmSearch参数 caption: "查找", Find: "Go!", closeAfterSearch: true },{});
当点击查询对话框中的“查询”按钮的时候,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代码改为:
- $("#gridTable").jqGrid("navGrid","#gridPager",{},{},{},{},
- {//与查询相关的prmSearch参数
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true,
- multipleSearch:true,
- groupOps:[{op:"AND",text:"全部"}]
- },{});
$("#gridTable").jqGrid("navGrid", "#gridPager", {},{},{},{}, { // 与查询相关的prmSearch参数 caption: "查找", Find: "Go!", closeAfterSearch: true, multipleSearch: true, groupOps: [{ op: "AND", text: "全部" }] },{});
或者
- varcomplexCriteriaSearch=function(){
- $("#gridTable").jqGrid("searchGrid",{
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true,
- multipleSearch:true,
- groupOps:[{op:"AND",text:"全部"}]
- });
- };
var complexCriteriaSearch = function() { $("#gridTable").jqGrid("searchGrid", { caption: "查找", Find: "Go!", closeAfterSearch: true, multipleSearch: true, groupOps: [{ op: "AND", text: "全部" }] }); };
除了选项上的不同以外,客户端的另一个不同之处在于,向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
即:
- nd:1278688214496
- page:1
- rows:15
- search:true
- searchField:id
- searchOper:ge
- searchString:9000
- sidx:
- sord:asc
nd: 1278688214496 page: 1 rows: 15 search: true searchField: id searchOper: ge searchString: 9000 sidx: 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
即:
- filters:{"groupOp":"AND","rules":[{"field":"id","op":"le","data":"1500"},{"field":"lastName","op":"bw","data":"LN-3"},{"field":"email","op":"cn","data":"sy"}]}
- nd:1278688110637
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
filters: {"groupOp":"AND","rules":[{"field":"id","op":"le","data":"1500"},{"field":"lastName","op":"bw","data":"LN-3"},{"field":"email","op":"cn","data":"sy"}]} nd: 1278688110637 page: 1 rows: 15 search: true sidx: 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列表。
- publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
- List<Criterion>criteria=newArrayList<Criterion>();
- JSONObjectjsonObject=JSONObject.fromObject(filters);
- JSONArrayrules=jsonObject.getJSONArray("rules");
- for(Objectobj:rules){
- JSONObjectrule=(JSONObject)obj;
- Stringfield=rule.getString("field");
- Stringop=rule.getString("op");
- Stringdata=rule.getString("data");
- Criterioncriterion=this.generateSearchCriterion(field,data,op);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- returncriteria;
- }
public List<Criterion> generateSearchCriteriaFromFilters(String filters) { List<Criterion> criteria = new ArrayList<Criterion>(); JSONObject jsonObject = JSONObject.fromObject(filters); JSONArray rules = jsonObject.getJSONArray("rules"); for(Object obj : rules) { JSONObject rule = (JSONObject) obj; String field = rule.getString("field"); String op = rule.getString("op"); String data = rule.getString("data"); Criterion criterion = this.generateSearchCriterion(field, data, op); if(criterion != null) { criteria.add(criterion); } } return criteria; }
其余部分的代码:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- importnet.sf.json.JSONArray;
- importnet.sf.json.JSONObject;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.dao.impl.Criterion.CompareType;
- importcom.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings("serial")
- publicabstractclassJqGridBaseAction<T>extendsActionSupport{
- privateList<T>gridModel=Collections.emptyList();
- privateIntegerrows=0;
- privateIntegerpage=0;
- privateIntegertotal=0;
- privateIntegerrecord=0;
- privateStringsord;
- privateStringsidx;
- privatebooleansearch;
- privateStringsearchField;
- privateStringsearchString;
- privateStringsearchOper;
- publicabstractintgetResultSize();
- publicabstractList<T>listResults(intfrom,intlength);
- //(1)添加filters成员变量
- privateStringfilters;
- publicabstractintgetResultSize(List<Criterion>criteria);
- publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
- publicStringrefreshGridModel(){
- try{
- List<Criterion>criteria=Collections.emptyList();
- if(search==true){
- criteria=newArrayList<Criterion>();
- //(2)将Filter转化为Criterion列表,并加入总的Criterion列表
- if(filters!=null&&filters.length()>0){
- criteria.addAll(this.generateSearchCriteriaFromFilters(filters));
- }
- //(3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表
- Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- intfrom=rows*(page-1);
- intlength=rows;
- List<T>results=Collections.emptyList();
- if(!criteria.isEmpty()){
- record=this.getResultSize(criteria);
- results=this.listResults(criteria,from,length);
- }else{
- record=this.getResultSize();
- results=this.listResults(from,length);
- }
- this.setGridModel(results);
- total=(int)Math.ceil((double)record/(double)rows);
- returnSUCCESS;
- }catch(Exceptione){
- e.printStackTrace();
- this.addActionError(e.getMessage());
- returnERROR;
- }
- }
- publicCriteriongenerateSearchCriterion(StringsearchField,
- StringsearchString,StringsearchOper){
- ...
- }
- publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
- List<Criterion>criteria=newArrayList<Criterion>();
- JSONObjectjsonObject=JSONObject.fromObject(filters);
- JSONArrayrules=jsonObject.getJSONArray("rules");
- for(Objectobj:rules){
- JSONObjectrule=(JSONObject)obj;
- Stringfield=rule.getString("field");
- Stringop=rule.getString("op");
- Stringdata=rule.getString("data");
- Criterioncriterion=this.generateSearchCriterion(field,data,op);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- returncriteria;
- }
- //getter和setter
- ...
- }
package cn.gengv.struts2ex.jqGrid; import java.util.ArrayList; import java.util.Collections; import java.util.List; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.dao.impl.Criterion.CompareType; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public abstract class JqGridBaseAction<T> extends ActionSupport { private List<T> gridModel = Collections.emptyList(); private Integer rows = 0; private Integer page = 0; private Integer total = 0; private Integer record = 0; private String sord; private String sidx; private boolean search; private String searchField; private String searchString; private String searchOper; public abstract int getResultSize(); public abstract List<T> listResults(int from, int length); // (1)添加filters成员变量 private String filters; public abstract int getResultSize(List<Criterion> criteria); public abstract List<T> listResults(List<Criterion> criteria, int from, int length); public String refreshGridModel() { try { List<Criterion> criteria = Collections.emptyList(); if(search == true) { criteria = new ArrayList<Criterion>(); // (2)将Filter转化为Criterion列表,并加入总的Criterion列表 if(filters != null && filters.length()>0) { criteria.addAll(this.generateSearchCriteriaFromFilters(filters)); } // (3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper); if(criterion != null) { criteria.add(criterion); } } int from = rows * (page - 1); int length = rows; List<T> results = Collections.emptyList(); if(!criteria.isEmpty()) { record = this.getResultSize(criteria); results = this.listResults(criteria, from, length); } else { record = this.getResultSize(); results = this.listResults(from, length); } this.setGridModel(results); total = (int) Math.ceil((double) record / (double) rows); return SUCCESS; } catch (Exception e) { e.printStackTrace(); this.addActionError(e.getMessage()); return ERROR; } } public Criterion generateSearchCriterion(String searchField, String searchString, String searchOper) { ... } public List<Criterion> generateSearchCriteriaFromFilters(String filters) { List<Criterion> criteria = new ArrayList<Criterion>(); JSONObject jsonObject = JSONObject.fromObject(filters); JSONArray rules = jsonObject.getJSONArray("rules"); for(Object obj : rules) { JSONObject rule = (JSONObject) obj; String field = rule.getString("field"); String op = rule.getString("op"); String data = rule.getString("data"); Criterion criterion = this.generateSearchCriterion(field, data, op); if(criterion != null) { criteria.add(criterion); } } return criteria; } //getter和setter ... }
经过如上修改,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的情况下,查询参数是这样的:
- firstName:FN-cjxxxds3
- lastName:LN-3iviu7o
- nd:1278692114137
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
- telNo:TEL-gzbn1w
firstName: FN-cjxxxds3 lastName: LN-3iviu7o nd: 1278692114137 page: 1 rows: 15 search: true sidx: sord: asc telNo: TEL-gzbn1w
而当stringResult设为true的情况下,查询参数会按照复杂条件查询的方式发送:
- 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"}]}
- nd:1278692302168
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
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"}]} nd: 1278692302168 page: 1 rows: 15 search: true sidx: 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类代码:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.dao.impl.Criterion.CompareType;
- importcom.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings("serial")
- publicabstractclassJqGridBaseAction<T>extendsActionSupport{
- privateList<T>gridModel=Collections.emptyList();
- privateIntegerrows=0;
- privateIntegerpage=0;
- privateIntegertotal=0;
- privateIntegerrecord=0;
- privateStringsord;
- privateStringsidx;
- //(1)添加和查询有关的成员变量search、searchField、searchString、searchOper
- privatebooleansearch;
- privateStringsearchField;
- privateStringsearchString;
- privateStringsearchOper;
- publicabstractintgetResultSize();
- publicabstractList<T>listResults(intfrom,intlength);
- //(2)添加用于根据条件进行查询的方法
- publicabstractintgetResultSize(List<Criterion>criteria);
- publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
- publicStringrefreshGridModel(){
- try{
- List<Criterion>criteria=Collections.emptyList();
- //(3)如果search值为true,则表明是查询请求
- if(search==true){
- //(4)通过searchField、searchString、searchOper生成通用的查询条件
- Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
- criteria=newArrayList<Criterion>();
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- intfrom=rows*(page-1);
- intlength=rows;
- List<T>results=Collections.emptyList();
- if(!criteria.isEmpty()){//(5)如果criteria列表不为空,则根据条件进行查询
- record=this.getResultSize(criteria);
- results=this.listResults(criteria,from,length);
- }else{
- record=this.getResultSize();
- results=this.listResults(from,length);
- }
- this.setGridModel(results);
- total=(int)Math.ceil((double)record/(double)rows);
- returnSUCCESS;
- }catch(Exceptione){
- e.printStackTrace();
- this.addActionError(e.getMessage());
- returnERROR;
- }
- }
- //(6)通过searchField、searchString、searchOper三个参数生成Criterion的方法
- publicCriteriongenerateSearchCriterion(StringsearchField,
- StringsearchString,StringsearchOper){
- Criterioncriterion=null;
- //(7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion
- if(searchField!=null&&searchString!=null
- &searchString.length()>0&&searchOper!=null){
- if("eq".equals(searchOper)){
- criterion=Criterion.getEqualCriterion(searchField,
- searchString,null);
- }elseif("ne".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.NE,
- searchField,searchString,null);
- }elseif("lt".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.LT,
- searchField,searchString,null);
- }elseif("le".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.LTE,
- searchField,searchString,null);
- }elseif("gt".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.GT,
- searchField,searchString,null);
- }elseif("ge".equals(searchOper)){
- criterion=Criterion.getCompareCriterion(CompareType.GTE,
- searchField,searchString,null);
- }elseif("bw".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,
- searchString+"%",null);
- }elseif("bn".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,
- searchString+"%",null);
- }elseif("ew".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,"%"
- +searchString,null);
- }elseif("en".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,"%"
- +searchString,null);
- }elseif("cn".equals(searchOper)){
- criterion=Criterion.getLikeCriterion(searchField,"%"
- +searchString+"%",null);
- }elseif("nc".equals(searchOper)){
- criterion=Criterion.getNotLikeCriterion(searchField,"%"
- +searchString+"%",null);
- }
- }
- returncriterion;
- }
- //getter和setter
- ...
- }
package cn.gengv.struts2ex.jqGrid; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.dao.impl.Criterion.CompareType; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public abstract class JqGridBaseAction<T> extends ActionSupport { private List<T> gridModel = Collections.emptyList(); private Integer rows = 0; private Integer page = 0; private Integer total = 0; private Integer record = 0; private String sord; private String sidx; // (1)添加和查询有关的成员变量search、searchField、searchString、searchOper private boolean search; private String searchField; private String searchString; private String searchOper; public abstract int getResultSize(); public abstract List<T> listResults(int from, int length); // (2)添加用于根据条件进行查询的方法 public abstract int getResultSize(List<Criterion> criteria); public abstract List<T> listResults(List<Criterion> criteria, int from, int length); public String refreshGridModel() { try { List<Criterion> criteria = Collections.emptyList(); // (3)如果search值为true,则表明是查询请求 if(search == true) { // (4)通过searchField、searchString、searchOper生成通用的查询条件 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper); criteria = new ArrayList<Criterion>(); if(criterion != null) { criteria.add(criterion); } } int from = rows * (page - 1); int length = rows; List<T> results = Collections.emptyList(); if(!criteria.isEmpty()) { // (5)如果criteria列表不为空,则根据条件进行查询 record = this.getResultSize(criteria); results = this.listResults(criteria, from, length); } else { record = this.getResultSize(); results = this.listResults(from, length); } this.setGridModel(results); total = (int) Math.ceil((double) record / (double) rows); return SUCCESS; } catch (Exception e) { e.printStackTrace(); this.addActionError(e.getMessage()); return ERROR; } } // (6)通过searchField、searchString、searchOper三个参数生成Criterion的方法 public Criterion generateSearchCriterion(String searchField, String searchString, String searchOper) { Criterion criterion = null; // (7)如果searchField、searchString、searchOper均不为null,且searchString不为空字符串时,则创建Criterion if (searchField != null && searchString != null & searchString.length() > 0 && searchOper != null) { if ("eq".equals(searchOper)) { criterion = Criterion.getEqualCriterion(searchField, searchString, null); } else if ("ne".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.NE, searchField, searchString, null); } else if ("lt".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.LT, searchField, searchString, null); } else if ("le".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.LTE, searchField, searchString, null); } else if ("gt".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.GT, searchField, searchString, null); } else if ("ge".equals(searchOper)) { criterion = Criterion.getCompareCriterion(CompareType.GTE, searchField, searchString, null); } else if ("bw".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, searchString + "%", null); } else if ("bn".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, searchString + "%", null); } else if ("ew".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, "%" + searchString, null); } else if ("en".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, "%" + searchString, null); } else if ("cn".equals(searchOper)) { criterion = Criterion.getLikeCriterion(searchField, "%" + searchString + "%", null); } else if ("nc".equals(searchOper)) { criterion = Criterion.getNotLikeCriterion(searchField, "%" + searchString + "%", null); } } return criterion; } // getter和setter ... }
说明:
- (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类的代码:
- packagecom.byzl.hare.dao.impl;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- publicclassCriterion{
- publicstaticenumCriterionType{
- EQUAL,LIKE,COMPARE,NOT_LIKE
- }
- publicstaticenumCompareType{
- GT,GTE,LT,LTE,EQ,NE
- }
- privateCriterionTypecriterionType;
- privateStringtableName;
- privateStringfield;
- privateObjectvalue;
- //将Criteria转换为SQL条件语句
- publicstaticStringconvertToSql(List<Criterion>criteria){
- StringcriteriaString="";
- StringBuildersb=newStringBuilder();
- for(Criterioncriterion:criteria){
- Stringprefix=criterion.getFieldPrefix();
- switch(criterion.getCriterionType()){
- caseEQUAL:
- sb.append(prefix+criterion.getField()+"=?and");
- break;
- caseLIKE:
- sb.append(prefix+criterion.getField()+"like?and");
- break;
- caseNOT_LIKE:
- sb.append(prefix+criterion.getField()+"notlike?and");
- break;
- caseCOMPARE:
- CompareTypecompareType=((CompareCriterion)criterion)
- .getCompareType();
- switch(compareType){
- caseEQ:
- sb.append(prefix+criterion.getField()+"=?and");
- break;
- caseNE:
- sb.append(prefix+criterion.getField()+"<>?and");
- break;
- caseGT:
- sb.append(prefix+criterion.getField()+">?and");
- break;
- caseGTE:
- sb.append(prefix+criterion.getField()+">=?and");
- break;
- caseLT:
- sb.append(prefix+criterion.getField()+"<?and");
- break;
- caseLTE:
- sb.append(prefix+criterion.getField()+"<=?and");
- break;
- }
- break;
- }
- }
- inti=-1;
- if((i=sb.lastIndexOf("and"))!=-1){
- criteriaString=sb.substring(0,i);
- }
- returncriteriaString;
- }
- //将Criteria各条件的值转换为List<Object>
- publicstaticList<Object>getCriteriaValues(List<Criterion>criteria){
- List<Object>criteriaValues=criteria.isEmpty()?Collections
- .emptyList():newArrayList<Object>();
- for(Criterioncriterion:criteria){
- criteriaValues.add(criterion.getValue());
- }
- returncriteriaValues;
- }
- publicCriterionTypegetCriterionType(){
- returncriterionType;
- }
- publicvoidsetCriterionType(CriterionTypecriterionType){
- this.criterionType=criterionType;
- }
- publicStringgetField(){
- returnfield;
- }
- publicvoidsetField(Stringfield){
- this.field=field;
- }
- publicObjectgetValue(){
- returnvalue;
- }
- publicvoidsetValue(Objectvalue){
- this.value=value;
- }
- publicstaticCriteriongetCompareCriterion(CompareTypecompareType,
- Stringfield,Objectvalue,StringtableName){
- CompareCriterioncompareCriterion=newCompareCriterion();
- compareCriterion.setCriterionType(CriterionType.COMPARE);
- compareCriterion.setCompareType(compareType);
- compareCriterion.setField(field);
- compareCriterion.setValue(value);
- compareCriterion.setTableName(tableName);
- returncompareCriterion;
- }
- publicstaticCriteriongetLikeCriterion(Stringfield,Objectvalue,
- StringtableName){
- LikeCriterionlikeCriterion=newLikeCriterion();
- likeCriterion.setCriterionType(CriterionType.LIKE);
- likeCriterion.setField(field);
- likeCriterion.setValue(value);
- likeCriterion.setTableName(tableName);
- returnlikeCriterion;
- }
- publicstaticCriteriongetNotLikeCriterion(Stringfield,Objectvalue,
- StringtableName){
- NotLikeCriterionnotLikeCriterion=newNotLikeCriterion();
- notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE);
- notLikeCriterion.setField(field);
- notLikeCriterion.setValue(value);
- notLikeCriterion.setTableName(tableName);
- returnnotLikeCriterion;
- }
- publicstaticCriteriongetEqualCriterion(Stringfield,Objectvalue,
- StringtableName){
- EqualCriterionequalCriterion=newEqualCriterion();
- equalCriterion.setCriterionType(CriterionType.EQUAL);
- equalCriterion.setField(field);
- equalCriterion.setValue(value);
- equalCriterion.setTableName(tableName);
- returnequalCriterion;
- }
- publicstaticclassLikeCriterionextendsCriterion{
- }
- publicstaticclassNotLikeCriterionextendsCriterion{
- }
- publicstaticclassEqualCriterionextendsCriterion{
- }
- publicstaticclassCompareCriterionextendsCriterion{
- privateCompareTypecompareType;
- publicCompareTypegetCompareType(){
- returncompareType;
- }
- publicvoidsetCompareType(CompareTypecompareType){
- this.compareType=compareType;
- }
- }
- publicStringgetTableName(){
- returntableName;
- }
- publicvoidsetTableName(StringtableName){
- this.tableName=tableName;
- }
- publicStringgetFieldPrefix(){
- return(tableName==null||tableName.length()==0)?"":tableName
- +".";
- }
- }
package com.byzl.hare.dao.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Criterion { public static enum CriterionType { EQUAL, LIKE, COMPARE, NOT_LIKE } public static enum CompareType { GT, GTE, LT, LTE, EQ, NE } private CriterionType criterionType; private String tableName; private String field; private Object value; // 将Criteria转换为SQL条件语句 public static String convertToSql(List<Criterion> criteria) { String criteriaString = ""; StringBuilder sb = new StringBuilder(); for (Criterion criterion : criteria) { String prefix = criterion.getFieldPrefix(); switch (criterion.getCriterionType()) { case EQUAL: sb.append(prefix + criterion.getField() + "=? and "); break; case LIKE: sb.append(prefix + criterion.getField() + " like ? and "); break; case NOT_LIKE: sb.append(prefix + criterion.getField() + " not like ? and "); break; case COMPARE: CompareType compareType = ((CompareCriterion) criterion) .getCompareType(); switch (compareType) { case EQ: sb.append(prefix + criterion.getField() + "=? and "); break; case NE: sb.append(prefix + criterion.getField() + "<>? and "); break; case GT: sb.append(prefix + criterion.getField() + ">? and "); break; case GTE: sb.append(prefix + criterion.getField() + ">=? and "); break; case LT: sb.append(prefix + criterion.getField() + "<? and "); break; case LTE: sb.append(prefix + criterion.getField() + "<=? and "); break; } break; } } int i = -1; if ((i = sb.lastIndexOf(" and ")) != -1) { criteriaString = sb.substring(0, i); } return criteriaString; } // 将Criteria各条件的值转换为List<Object> public static List<Object> getCriteriaValues(List<Criterion> criteria) { List<Object> criteriaValues = criteria.isEmpty() ? Collections .emptyList() : new ArrayList<Object>(); for (Criterion criterion : criteria) { criteriaValues.add(criterion.getValue()); } return criteriaValues; } public CriterionType getCriterionType() { return criterionType; } public void setCriterionType(CriterionType criterionType) { this.criterionType = criterionType; } public String getField() { return field; } public void setField(String field) { this.field = field; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } public static Criterion getCompareCriterion(CompareType compareType, String field, Object value, String tableName) { CompareCriterion compareCriterion = new CompareCriterion(); compareCriterion.setCriterionType(CriterionType.COMPARE); compareCriterion.setCompareType(compareType); compareCriterion.setField(field); compareCriterion.setValue(value); compareCriterion.setTableName(tableName); return compareCriterion; } public static Criterion getLikeCriterion(String field, Object value, String tableName) { LikeCriterion likeCriterion = new LikeCriterion(); likeCriterion.setCriterionType(CriterionType.LIKE); likeCriterion.setField(field); likeCriterion.setValue(value); likeCriterion.setTableName(tableName); return likeCriterion; } public static Criterion getNotLikeCriterion(String field, Object value, String tableName) { NotLikeCriterion notLikeCriterion = new NotLikeCriterion(); notLikeCriterion.setCriterionType(CriterionType.NOT_LIKE); notLikeCriterion.setField(field); notLikeCriterion.setValue(value); notLikeCriterion.setTableName(tableName); return notLikeCriterion; } public static Criterion getEqualCriterion(String field, Object value, String tableName) { EqualCriterion equalCriterion = new EqualCriterion(); equalCriterion.setCriterionType(CriterionType.EQUAL); equalCriterion.setField(field); equalCriterion.setValue(value); equalCriterion.setTableName(tableName); return equalCriterion; } public static class LikeCriterion extends Criterion { } public static class NotLikeCriterion extends Criterion { } public static class EqualCriterion extends Criterion { } public static class CompareCriterion extends Criterion { private CompareType compareType; public CompareType getCompareType() { return compareType; } public void setCompareType(CompareType compareType) { this.compareType = compareType; } } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public String getFieldPrefix() { return (tableName == null || tableName.length() == 0) ? "" : tableName + "."; } }
简要说明一下:
- 我把Criterion分成4类:EqualCriterion、CompareCriterion、LikeCriterion、NotLikeCriterion。(具体划分方式全为使用方便)
- 另外还有两个静态方法:convertToSql和getCriteriaValues,用来将Criterion列表转化为JdbcTemplate需要的SQL子句和参数列表。
回到ListContactsAction,代码如下:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.Collections;
- importjava.util.List;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.model.Contact;
- importcom.byzl.hare.service.ContactService;
- @SuppressWarnings("serial")
- publicclassListContactsActionextendsJqGridBaseAction<Contact>{
- privateContactServicecontactService;
- @Override
- publicStringexecute(){
- returnthis.refreshGridModel();
- }
- @Override
- publicintgetResultSize(){
- returnthis.contactService.queryResultsCount(null);
- }
- @Override
- publicList<Contact>listResults(intfrom,intlength){
- returnthis.contactService.queryByPage(null,from,length);
- }
- @Override
- publicintgetResultSize(List<Criterion>criteria){
- returnthis.contactService.queryResultsCount(criteria);
- }
- @Override
- publicList<Contact>listResults(List<Criterion>criteria,intfrom,intlength){
- List<Contact>results=Collections.emptyList();
- results=this.contactService.queryByPage(criteria,from,length);
- returnresults;
- }
- publicvoidsetContactService(ContactServicecontactService){
- this.contactService=contactService;
- }
- }
package cn.gengv.struts2ex.jqGrid; import java.util.Collections; import java.util.List; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.model.Contact; import com.byzl.hare.service.ContactService; @SuppressWarnings("serial") public class ListContactsAction extends JqGridBaseAction<Contact> { private ContactService contactService; @Override public String execute() { return this.refreshGridModel(); } @Override public int getResultSize() { return this.contactService.queryResultsCount(null); } @Override public List<Contact> listResults(int from, int length) { return this.contactService.queryByPage(null, from, length); } @Override public int getResultSize(List<Criterion> criteria) { return this.contactService.queryResultsCount(criteria); } @Override public List<Contact> listResults(List<Criterion> criteria, int from, int length) { List<Contact> results = Collections.emptyList(); results = this.contactService.queryByPage(criteria, from, length); return results; } public void setContactService(ContactService contactService) { this.contactService = contactService; } }
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参数中设置这些选项(参见上一篇),作用效果是相同的。
即
- varsingleCriterionSearch=function(){
- $("#gridTable").jqGrid("searchGrid",{
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true
- });
- };
var singleCriterionSearch = function() { $("#gridTable").jqGrid("searchGrid", { caption: "查找", Find: "Go!", closeAfterSearch: true }); };
等同于
- $("#gridTable").jqGrid("navGrid","#gridPager",{},{},{},{},
- {//与查询相关的prmSearch参数
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true
- },{});
$("#gridTable").jqGrid("navGrid", "#gridPager", {},{},{},{}, { // 与查询相关的prmSearch参数 caption: "查找", Find: "Go!", closeAfterSearch: true },{});
当点击查询对话框中的“查询”按钮的时候,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代码改为:
- $("#gridTable").jqGrid("navGrid","#gridPager",{},{},{},{},
- {//与查询相关的prmSearch参数
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true,
- multipleSearch:true,
- groupOps:[{op:"AND",text:"全部"}]
- },{});
$("#gridTable").jqGrid("navGrid", "#gridPager", {},{},{},{}, { // 与查询相关的prmSearch参数 caption: "查找", Find: "Go!", closeAfterSearch: true, multipleSearch: true, groupOps: [{ op: "AND", text: "全部" }] },{});
或者
- varcomplexCriteriaSearch=function(){
- $("#gridTable").jqGrid("searchGrid",{
- caption:"查找",
- Find:"Go!",
- closeAfterSearch:true,
- multipleSearch:true,
- groupOps:[{op:"AND",text:"全部"}]
- });
- };
var complexCriteriaSearch = function() { $("#gridTable").jqGrid("searchGrid", { caption: "查找", Find: "Go!", closeAfterSearch: true, multipleSearch: true, groupOps: [{ op: "AND", text: "全部" }] }); };
除了选项上的不同以外,客户端的另一个不同之处在于,向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
即:
- nd:1278688214496
- page:1
- rows:15
- search:true
- searchField:id
- searchOper:ge
- searchString:9000
- sidx:
- sord:asc
nd: 1278688214496 page: 1 rows: 15 search: true searchField: id searchOper: ge searchString: 9000 sidx: 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
即:
- filters:{"groupOp":"AND","rules":[{"field":"id","op":"le","data":"1500"},{"field":"lastName","op":"bw","data":"LN-3"},{"field":"email","op":"cn","data":"sy"}]}
- nd:1278688110637
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
filters: {"groupOp":"AND","rules":[{"field":"id","op":"le","data":"1500"},{"field":"lastName","op":"bw","data":"LN-3"},{"field":"email","op":"cn","data":"sy"}]} nd: 1278688110637 page: 1 rows: 15 search: true sidx: 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列表。
- publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
- List<Criterion>criteria=newArrayList<Criterion>();
- JSONObjectjsonObject=JSONObject.fromObject(filters);
- JSONArrayrules=jsonObject.getJSONArray("rules");
- for(Objectobj:rules){
- JSONObjectrule=(JSONObject)obj;
- Stringfield=rule.getString("field");
- Stringop=rule.getString("op");
- Stringdata=rule.getString("data");
- Criterioncriterion=this.generateSearchCriterion(field,data,op);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- returncriteria;
- }
public List<Criterion> generateSearchCriteriaFromFilters(String filters) { List<Criterion> criteria = new ArrayList<Criterion>(); JSONObject jsonObject = JSONObject.fromObject(filters); JSONArray rules = jsonObject.getJSONArray("rules"); for(Object obj : rules) { JSONObject rule = (JSONObject) obj; String field = rule.getString("field"); String op = rule.getString("op"); String data = rule.getString("data"); Criterion criterion = this.generateSearchCriterion(field, data, op); if(criterion != null) { criteria.add(criterion); } } return criteria; }
其余部分的代码:
- packagecn.gengv.struts2ex.jqGrid;
- importjava.util.ArrayList;
- importjava.util.Collections;
- importjava.util.List;
- importnet.sf.json.JSONArray;
- importnet.sf.json.JSONObject;
- importcom.byzl.hare.dao.impl.Criterion;
- importcom.byzl.hare.dao.impl.Criterion.CompareType;
- importcom.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings("serial")
- publicabstractclassJqGridBaseAction<T>extendsActionSupport{
- privateList<T>gridModel=Collections.emptyList();
- privateIntegerrows=0;
- privateIntegerpage=0;
- privateIntegertotal=0;
- privateIntegerrecord=0;
- privateStringsord;
- privateStringsidx;
- privatebooleansearch;
- privateStringsearchField;
- privateStringsearchString;
- privateStringsearchOper;
- publicabstractintgetResultSize();
- publicabstractList<T>listResults(intfrom,intlength);
- //(1)添加filters成员变量
- privateStringfilters;
- publicabstractintgetResultSize(List<Criterion>criteria);
- publicabstractList<T>listResults(List<Criterion>criteria,intfrom,intlength);
- publicStringrefreshGridModel(){
- try{
- List<Criterion>criteria=Collections.emptyList();
- if(search==true){
- criteria=newArrayList<Criterion>();
- //(2)将Filter转化为Criterion列表,并加入总的Criterion列表
- if(filters!=null&&filters.length()>0){
- criteria.addAll(this.generateSearchCriteriaFromFilters(filters));
- }
- //(3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表
- Criterioncriterion=this.generateSearchCriterion(searchField,searchString,searchOper);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- intfrom=rows*(page-1);
- intlength=rows;
- List<T>results=Collections.emptyList();
- if(!criteria.isEmpty()){
- record=this.getResultSize(criteria);
- results=this.listResults(criteria,from,length);
- }else{
- record=this.getResultSize();
- results=this.listResults(from,length);
- }
- this.setGridModel(results);
- total=(int)Math.ceil((double)record/(double)rows);
- returnSUCCESS;
- }catch(Exceptione){
- e.printStackTrace();
- this.addActionError(e.getMessage());
- returnERROR;
- }
- }
- publicCriteriongenerateSearchCriterion(StringsearchField,
- StringsearchString,StringsearchOper){
- ...
- }
- publicList<Criterion>generateSearchCriteriaFromFilters(Stringfilters){
- List<Criterion>criteria=newArrayList<Criterion>();
- JSONObjectjsonObject=JSONObject.fromObject(filters);
- JSONArrayrules=jsonObject.getJSONArray("rules");
- for(Objectobj:rules){
- JSONObjectrule=(JSONObject)obj;
- Stringfield=rule.getString("field");
- Stringop=rule.getString("op");
- Stringdata=rule.getString("data");
- Criterioncriterion=this.generateSearchCriterion(field,data,op);
- if(criterion!=null){
- criteria.add(criterion);
- }
- }
- returncriteria;
- }
- //getter和setter
- ...
- }
package cn.gengv.struts2ex.jqGrid; import java.util.ArrayList; import java.util.Collections; import java.util.List; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import com.byzl.hare.dao.impl.Criterion; import com.byzl.hare.dao.impl.Criterion.CompareType; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public abstract class JqGridBaseAction<T> extends ActionSupport { private List<T> gridModel = Collections.emptyList(); private Integer rows = 0; private Integer page = 0; private Integer total = 0; private Integer record = 0; private String sord; private String sidx; private boolean search; private String searchField; private String searchString; private String searchOper; public abstract int getResultSize(); public abstract List<T> listResults(int from, int length); // (1)添加filters成员变量 private String filters; public abstract int getResultSize(List<Criterion> criteria); public abstract List<T> listResults(List<Criterion> criteria, int from, int length); public String refreshGridModel() { try { List<Criterion> criteria = Collections.emptyList(); if(search == true) { criteria = new ArrayList<Criterion>(); // (2)将Filter转化为Criterion列表,并加入总的Criterion列表 if(filters != null && filters.length()>0) { criteria.addAll(this.generateSearchCriteriaFromFilters(filters)); } // (3)将searchField、searchString、searchOper转化为Criterion,并加入总的Criterion列表 Criterion criterion = this.generateSearchCriterion(searchField, searchString, searchOper); if(criterion != null) { criteria.add(criterion); } } int from = rows * (page - 1); int length = rows; List<T> results = Collections.emptyList(); if(!criteria.isEmpty()) { record = this.getResultSize(criteria); results = this.listResults(criteria, from, length); } else { record = this.getResultSize(); results = this.listResults(from, length); } this.setGridModel(results); total = (int) Math.ceil((double) record / (double) rows); return SUCCESS; } catch (Exception e) { e.printStackTrace(); this.addActionError(e.getMessage()); return ERROR; } } public Criterion generateSearchCriterion(String searchField, String searchString, String searchOper) { ... } public List<Criterion> generateSearchCriteriaFromFilters(String filters) { List<Criterion> criteria = new ArrayList<Criterion>(); JSONObject jsonObject = JSONObject.fromObject(filters); JSONArray rules = jsonObject.getJSONArray("rules"); for(Object obj : rules) { JSONObject rule = (JSONObject) obj; String field = rule.getString("field"); String op = rule.getString("op"); String data = rule.getString("data"); Criterion criterion = this.generateSearchCriterion(field, data, op); if(criterion != null) { criteria.add(criterion); } } return criteria; } //getter和setter ... }
经过如上修改,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的情况下,查询参数是这样的:
- firstName:FN-cjxxxds3
- lastName:LN-3iviu7o
- nd:1278692114137
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
- telNo:TEL-gzbn1w
firstName: FN-cjxxxds3 lastName: LN-3iviu7o nd: 1278692114137 page: 1 rows: 15 search: true sidx: sord: asc telNo: TEL-gzbn1w
而当stringResult设为true的情况下,查询参数会按照复杂条件查询的方式发送:
- 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"}]}
- nd:1278692302168
- page:1
- rows:15
- search:true
- sidx:
- sord:asc
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"}]} nd: 1278692302168 page: 1 rows: 15 search: true sidx: 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();