ext+java综合查询解决方案
软件开发完成,客户突然要求可以实现按照所有字段进行查询,由于项目工程比较大,每个页面需要添加一个查询窗口,后台需要依据传入参数进行改写hql或者sql语句,这样工作量很大,于是有了以下解决方案:
(1)每个查询为了美观,可以再ext基础上弹出一个查询界面。由于添加窗口是好的,可以基于添加窗口,界面不做任何调整,窗口里面的处理方法写为通用的,这样减少了页面维护工作。
(2)基于查询需要支持> ,< =,包含等比较,再输入框中输入>,<,=默认为包含,然后让输入值,比如要查询价格大于0.8的,在文本框中输入>0.8
(3)本软件使用ext3.0 struts 2.1 herbernate3版本,struts接受参数,会自动设置参数,并封装如对象,可以做一个方法传入一个对象依据这个对象进行中和查询,由于客户端传入的参数为>0.8无法转化为需要的float类型,在这里配置过滤器,将>过滤,然后把传入的name(key)与value(value)放入session
(4)创建查询分析器 遍历session中所有的值,并用正则表达式过滤掉所有的其他非必要信息。然后依据java反射动态调用方法。但由于某些查询设计到外键,也就是herbernate中的子对象,一级一级调用get方法最后依据AbstractEntityPersister获取最后一个对象的主键字段名称,进行hql语句拼写,然后设置参数,并查询,由于接口需要通用性强,返回一个泛型,增强了程序的通用性。
以下为关键部分代码加说明:
(1)页面ext查询界面实现
//创建查询
var createselectWindow = function(){
var postForm = new Ext.form.FormPanel({
rederTo:'createWin',
width:350,height:450,frame:true,
layout:'form',labelWidth:60,labelAlign:'right',
items:[client_clientname,client_clientpersonname,client_clientpersontel,client_clienttype],
buttonAlign:'center',
buttons:[{xtype:'button',text:'查询',
handler:function(){
//详细下面有改方法
var param = getFormJson(postForm);
//将json转换为对象
var Object=Ext.decode(param);
//防止分页,刷新丢失查询条件
store.on("beforeload", function(){Ext.apply(this.baseParams,Object);});
//重现加载store
store.load({params:Object});
}
},{
text:'取消',
handler:function(){
postWindow.destroy();
}
}]
});
var postWindow = new Ext.Window({
title:'客户信息查询',width:300,height:190,
collapsible:true,maximizable:true,
layout:'fit',plain:true,modal:'true',items:postForm
});
postWindow.show();
return postForm;
};
//中间设计到的其他关键代码
//将form表单中的所有提交内容准换为json格式
function getFormJson(postForm){
var param = '{';
postForm.getForm().items.each(function(f,index,length){
var tmp = '"' + f.getName() + '":"' + f.getValue() + '",';
param += tmp;
});
param = param.substr(0,param.length - 1)
param+="}";
return param;
}
function select(postForm,store){
//将form中的参数转化为json
var param = getFormJson(postForm);
//将json转化为对象
var Object=Ext.decode(param);
//防止分页丢失数据 刷新丢失数据
store.on("beforeload", function(){Ext.apply(this.baseParams,Object);});
//一句查询参数重新加载数据
store.load({params:Object});
}
这样提交请求就没有什么问题了,以后为后台主要代码:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
UserIncep ui = new UserIncep();
HttpServletRequest request1 = (HttpServletRequest) request;
String action = request1.getServletPath();
//过滤掉< > =生成新的request对象,防止>0.1被当成字符串处理,这个方法下面有解释
ParameterRequestWrapper ppw=JsonUtil.getRequestParams((HttpServletRequest) request);
String params = ppw.getParamsjson();
String uri = request1.getRequestURI();// 返回请求行中的资源名称
String url = request1.getRequestURL().toString();// 获得客户端发送请求的完整url
String ip = request1.getRemoteAddr();// 返回发出请求的IP地址
String host = request1.getRemoteHost();// 返回发出请求的客户机的主机名
int port = request1.getRemotePort();// 返回发出请求的客户机的端口号。
//继续调用,这里用ppw,不用原来的request
chain.doFilter(ppw, response);
return ;
}
转化请求参数处理方法
//通过获取request里面的所有参数,去掉< > =生成新的request,保留原来request中的数据
public static ParameterRequestWrapper getRequestParams(HttpServletRequest request) {
Enumeration enu = request.getParameterNames();
StringBuffer sb=new StringBuffer();
HashMap m=new HashMap(request.getParameterMap());
HttpSession session=request.getSession();
int count=0;
String setstr=null;
while (enu.hasMoreElements()) {
String paraName = (String) enu.nextElement();
String requeststr = request.getParameter(paraName);
//System.out.println(paraName.substring(paraName.lastIndexOf(".")+1, paraName.length()));
count=FormatUtil.getCount(paraName, "\\.");
setstr=paraName.substring(paraName.lastIndexOf(".")+1, paraName.length());
//count==1?requeststr.substring(1, requeststr.length()):requeststr
if(requeststr.startsWith(">")){
m.put(paraName, requeststr.substring(1, requeststr.length()));
session.setAttribute(count==1?setstr:requeststr, HqlEnum.MORE);
}
else if(requeststr.startsWith("<")){
m.put(paraName, requeststr.substring(1, requeststr.length()));
session.setAttribute(count==1?setstr:requeststr, HqlEnum.LESS);
}
else if(requeststr.startsWith("=")){
m.put(paraName, requeststr.substring(1, requeststr.length()));
session.setAttribute(count==1?setstr:requeststr, HqlEnum.EQ);
}
else {
m.put(paraName, requeststr);
session.setAttribute(count==1?setstr:requeststr, HqlEnum.Like);
}
//name.age.page
sb.append(paraName).append("=").append((requeststr)).append("&");
}
ParameterRequestWrapper wrapRequest=new ParameterRequestWrapper(request,m);
wrapRequest.setParamsjson(sb.toString());
return wrapRequest;
}
依据对象查找数据库方法
//依据obj查找合适的对象
public Query getHql(Object obj,SessionFactory sf){
if(obj==null){
return null;
}
List<Object>object=new ArrayList<Object>();
Class oclass=obj.getClass();
String classname=oclass.getSimpleName();
Field fields[]=oclass.getDeclaredFields();
Object returnvalue=null;
//查询所有数据的hql语句
StringBuffer sqlsb=new StringBuffer("from "+classname+" abstfind ");
//查询总数量的hql语句
StringBuffer sizebuff=new StringBuffer("select count(*) from "+classname+" abstfind ");
boolean b=true;
HttpServletRequest request=ServletActionContext.getRequest();
//获取session中所有的名称
Enumeration<String> s=request.getSession().getAttributeNames();
String sessionname=null;
Object sessionvalue=null;
String selname="";
//遍历session中的值
while(s.hasMoreElements()){
sessionname=s.nextElement();
sessionvalue=(String) request.getSession().getAttribute(sessionname);
//过滤其他session数据
if(sessionname.contains(".")){
try {
//动态方法调用 client.product.name 会调用client对象的getProduct()方法,并用返回值调用getName()方法,最后返回getName()的返回值
returnvalue = geterMethodInvoke(sessionname, obj);
if(null!=returnvalue){
//如果是hibernate对象,则按照子对象主键查询=
//如果是基本了类型或者String 从session里面对于的比较关系,然后按照关系进行比较查询
Object sobj=ServletActionContext.getRequest().getSession().getAttribute(sessionname);
//初始化基本查询selname给对象起别名
if(b){selname=sessionname.substring(0,sessionname.indexOf("."));sqlsb.append(selname).append(" where ");b=false;}
if(sobj!=null){
if(sobj==HqlEnum.MORE){
//将需要传递的参数放到集合中方便设值
object.add(returnvalue);
//组合查询语句
sqlsb.append(selname).append(sessionname).append(">?");sqlsb.append(" and ");
sizebuff.append(selname).append(sessionname).append(">?");sqlsb.append(" and ");
}else if(sobj==HqlEnum.LESS){
object.add(returnvalue);
sqlsb.append(selname).append(sessionname).append("<?");sqlsb.append(" and ");
sizebuff.append(selname).append(sessionname).append(">?");sqlsb.append(" and ");
}else if(sobj==HqlEnum.EQ){
object.add(returnvalue);
sqlsb.append(selname).append(sessionname).append("=?");sqlsb.append(" and ");
sizebuff.append(selname).append(sessionname).append("=?");sqlsb.append(" and ");
}else if(sobj==HqlEnum.Like){
object.add("%"+returnvalue+"%");
sqlsb.append(selname).append(sessionname).append(" like ?");sqlsb.append(" and ");
sizebuff.append(selname).append(sessionname).append(" like ?");sqlsb.append(" and ");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//去掉最后一个and语句
String hql=sqlsb.substring(0, sqlsb.length()-4);
String hqlbuff=sizebuff.substring(0, sqlsb.length()-4);
Query query=sf.getCurrentSession().createQuery(hql);
Query querybuff=sf.getCurrentSession().createQuery(hql);
//将值设值到查询中
int i=0;
for(Object o:object){
try {
//依据对象类型,动态调用query的方法
query.getClass().getMethod("set"+o.getClass().getSimpleName(),new Class[]{int.class, o.getClass()}).invoke(query, new Object[] {i,o});
i++;
} catch (Exception e) {
e.printStackTrace();
}
}
//保存数据总数
maxsize=Integer.parseInt(querybuff.uniqueResult().toString());
return query;
}
以下为动态方法调用接口
public Object geterMethodInvoke(String str,Object obj){
String fieldstrs[]=str.split("//.");
boolean b=true;
Object returnvalue=null;
try {
for(String s:fieldstrs){
if(b)
b=false;
else if(returnvalue==null)
returnvalue=obj.getClass().getMethod("get" + FormatUtil.toUpperCaseFirstOne(s), new Class[] {})
.invoke(obj, new Object[] {});
else{
returnvalue=obj.getClass().getMethod("get" + FormatUtil.toUpperCaseFirstOne(s), new Class[] {})
.invoke(returnvalue, new Object[] {});
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnvalue;
}

浙公网安备 33010602011771号