首先说明一下,什么是jqGrid的单字段查询。就是只能通过一个字段作为查询条件的查询。虽然大多数情况下,系统功能需要的查询,都是多个字段组合查询的,jqGrid也提供组合多个字段的查询,但是组合多个字段的查询,其实基于的原理还是单字段的查询。所以这里主要介绍一下单字段的查询,以后有机会在来说明一下高级一点的多字段组合查询。
大家可以先看看图片,对单字段查询有一个直观的了解(图片来源于jqGrid的wiki)
这里需要注意的几点分别说明如下:
首先,其实默认jqGrid就有这个功能,所以,向上一篇文章中的例子一样,基本上不需要在js中添加其他的代码。
其次,哪些字段能作为单字段查询,哪些字段不能,这是在jqGrid的colModel属性中可以进行设置的。比如,如果我们对某一个列的数据设置如下:{name:'userName',index:'usrName', width:110,search=false} 那么这个userName列是不会在单字段查询中显示出来的。
第三,点击上面图中的"Find"按钮之后,jqGrid会额外的向服务器发送几个参数过去。想必你已经猜到了,这些参数就是图片中显示的:查询字段searchField,查询操作searchOper以及查询值searchString。这里之所以说是额外的参数,是相对于默认情况下的参数,比如前一篇文章中所说的page,sidx,sord,rows,_search,nd这些参数而言的。当然,这里_search参数的值是true。
第四,最烦处理的,就是如何把我们的searchOper的参数值,转换为对数据库记录的查询操作。
页面上显示的操作,主要包括'equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'。相应的,后台获取到的searchOper的值,对应的是'eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'。
最最简单的想法就是像我这养,写一个方法来处理:(以下的例子是基于Hibernate写的)
/**
* 根据参数获取查询HQL的语句(如果是日期字段可能会出问题)
* @param sField 字段名称
* @param sOper 操作名称
* @param sValue 值
* @return
*/
public static String getOperation(String sField, String sOper,String sValue){
if(sValue==null || sValue.trim().length() ==0)
return "";
String result = "";
if(sOper.trim().equals("eq")) //等于
result = sField + "='" + sValue +"' ";
else if(sOper.trim().equals("ne")) //不等于
result = sField + " != '"+ sValue+"' ";
else if(sOper.trim().equals("lt")) //小于
result = sField + " < '"+ sValue+"' ";
else if(sOper.trim().equals("le")) //小于等于
result = sField + " <= '"+ sValue+"' ";
else if(sOper.trim().equals("gt")) //大于
result = sField + " > '"+ sValue+"' ";
else if(sOper.trim().equals("ge")) //大于等于
result = sField + " >= '"+ sValue+"' ";
else if(sOper.trim().equals("bw")) //以...开始
result = sField + " LIKE '"+ sValue+"%' ";
else if(sOper.trim().equals("bn")) //不以...开始
result = sField + " NOT LIKE '"+ sValue+"%' ";
else if(sOper.trim().equals("in")){ //包括
String[] sv = sValue.split(",");
String svString = "";
for(int i = 0 ;i
然后在dao类中,像如下这样进行查询和返回
@SuppressWarnings("unchecked")
public PageModel findAll(int page, int rows, String sidx, String sord,String sField,String sValue,String sOper)
{
Session s = null;
try
{
s = this.getSession();
//根据查询条件封装HQL语句
StringBuilder searchHQL = new StringBuilder ("");
if(sField != null && sOper != null){
String cond = SearchOperationUtil.getOperation(sField, sOper, sValue);
if(cond != null && cond.trim().length() != 0){
searchHQL.append(" WHERE brand.");
searchHQL.append(cond);
}
}
//得到总记录数
String queryCountHql = "select count(*) from MProductBrand brand" + searchHQL.toString();
Query query = s.createQuery(queryCountHql);
int records = ((Long)query.uniqueResult()).intValue();
int offset = (page-1) * rows;
searchHQL.append(" order by ");
searchHQL.append("brand.");
searchHQL.append(sidx);
searchHQL.append(" "+sord);
List datas = s.createQuery("from MProductBrand brand" + searchHQL.toString())
.setFirstResult(offset)
.setMaxResults(rows)
.list();
//得到结果集
PageModel pm = new PageModel();
int totalPage = records/rows;
if(records % rows > 0)
totalPage += 1;
pm.setTotal(totalPage);
pm.setDatas(datas);
pm.setPage(page);
pm.setRecords(records);
return pm;
}
finally
{
if(s!=null)
s.close();
}
}
当然了,在Action类中,我们还需要单独设置几个属性字段,并同时生成其相应的Getter和Setter。
private String searchField;
private String searchString;
private String searchOper;
......
@SuppressWarnings("unchecked")
public String queryAllBrand()
{
try
{
if(page == null ) page= "1";
if(sidx==null) sidx ="brandId";
if(rows==null) rows ="30";
if(sord==null) sord ="asc";
if(_search == null) _search="";
if(nd == null) nd = "0";
log.info("Page="+page+";sidx="+sidx+";rows="+rows+";sord="+sord+";_search="+_search+";nd="+nd);
log.info("searchField="+searchField+";searchValue="+searchString+";searchOper="+searchOper);
PageModel pm = this.brandService.findAll(Integer.parseInt(page), Integer.parseInt(rows),sidx,sord,searchField,searchString,searchOper);
//封装成JSON对象返回
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("text/json; charset=UTF-8");
PrintWriter out = response.getWriter();
JSONObject obj = new JSONObject();
obj.put("page", pm.getPage());
obj.put("total",pm.getTotal());
obj.put("records",pm.getRecords());
JSONArray lineitemArray = new JSONArray();
List data = pm.getDatas();
Iterator it = data.iterator();
while (it.hasNext()){
MProductBrand mpb = (MProductBrand)it.next();
lineitemArray.add(mpb.getJSON());
}
obj.put("rows", lineitemArray);
out.print(obj.toString());
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
看上面这个代码可能会有点糊涂,因为我们的Pojo对象中,还有一个重要的方法,把POJO转换为JSON对象。
//注意,JSON数据插入的顺序是和页面显示的顺序相关的。
public JSONObject getJSON(){
JSONObject json = new JSONObject();
json.put("brandId", brandId);
json.put("code", code);
json.put("brandName", brandName);
json.put("status", status);
return json;
}
感觉比较丑陋的,还是那个getOperation方法,一个是本身还有很多的bug,比如对空值的处理不够完善;二是对日期类型的处理功能基本上没有等等。呵呵,暂时先这样吧!有兴趣大家也可以帮忙修改一下!