Jeecg高级查询器

一、背景

      对于用户来讲查询功能按易用性分三个层次:

1. 最简单查询操作是一个输入框,全文检索,如百度,后台实现技术使用搜索引擎,需要设计和建立索引,技术较为复杂,适用于文档和信息数据库检索,但是结果很难精确控制。

2. 其次是定义字段查询,很多企业信息系统大多用的是这种查询,针对模块特定字段的查询有针对性、使用门坎低,适用于企业内部信息管理系统模块定制。

3. 最后一种是专门针对数据模型灵活的查询编辑器,使用难度最高,但是查询结果可以灵活和精确的控制,适用于有一定IT知识并对数据相当了解的用户,同时又可以避免直接将数据库暴露给用户带来的不安全隐患。

大家不难发现一个好的系统软件的查询基本会涵盖上述三种类型的查询功能

二、jeecg实现原理

Jeecg系统中模块主要使用第二种方式的查询功能,使用hibernate的QBC来封装前端查询条件,针对字段的定制过滤条件,最后转换为sql执行数据库查询。

现有方案优点:

1)默认无须复杂开发即可实现字段检索,支持范围、模糊、精确匹配查询

2)内置简单表达式支持:!*,实现非、模糊、数组等

现有方案缺点:

1)不支持or条件

2)不支持字段间操作field1=field2

3)不支持非hibernate关联表联合查询

4)单一字段条件只能出现一次

5)不支持sql嵌套

6)要支持上述功能需要额外开发定制工作

某些特定场景下,用户想要通过模块获得相关信息必须借助于第三方报表模块功能或求助于开发人员,无形中对报表模块开发带来一定压力。比如,用户要从模块中查询特殊的部分数据进行操作,现有查询功能无法做到,报表模块又不能操作编辑,这个时候就是高级查询器定制查询功能派上用场的时候了。

三、类似应用举例

我们来看看Outlook邮件查询设计:

1.全文检索型

2.字段定制型

3.高级查找

微软Team Foundation Server查询编辑器:

四、Jeecg查询器设计与实现

UI设计:首先要实现高级查询,必须要对数据表元信息metadata进行封装才可以通用化,我们利用datagrid标签中的columnList来自动生成字段下拉列表。作为高级查询,从易用的性和使用频率的角度功能所占UI比例不能太多,采用弹出窗口实现,如图:

这里的表格我使用了treegrid,因为更适合表达sql语法树,但没有实现树形结构,条件只加了大于、小于、包含等常用操作符,有待后续扩展sql嵌套。

右侧有查询历史,将每次查询的json条件保存在一个数组中实现快速重查,这个历史查询记录使用HTML5的localstorage保存在客户端缓存中,下次登录仍然有效,对于不支持localstorage的浏览器将使用cookie存储。

前后端交互:从到向前兼容性和对框架升级改动最小的因素考虑,将查询器组装的所有内容封装到一个json字符串,作为一个参数_sqlbuidler传递到后台,由后台控制条件组装,更加安全,防止sql注入等漏洞

        json格式示例:

[{“id”:101,”field”:”user_name”,”condition”:”like”,”value”:”%王%”,”relation”:”and”},{“id”:101,”field”:”user_name”,”condition”:”like”,”value”:”%王%”,”relation”:”and”}]

        后台封装处理java对象QueryCondition

package org.jeecgframework.web.demo.entity.test;
import java.util.List;
public class QueryCondition {
	String field;
	String type;
	String condition;
	String value;
	String relation;
	List<QueryCondition> children;
		public List<QueryCondition> getChildren() {
		return children;
	}
	public void setChildren(List<QueryCondition> children) {
		this.children = children;
	}
	public String getField() {
		return field;
	}
	public void setField(String field) {
		this.field = field;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getCondition() {
		return condition;
	}
	public void setCondition(String condition) {
		this.condition = condition;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public String getRelation() {
		return relation;
	}
	public void setRelation(String relation) {
		this.relation = relation;
	}
	public String toString(){
		StringBuffer sb =new StringBuffer();
		sb.append(this.relation).append(" ");
		sb.append(this.field).append(" ")
		.append(this.condition).append(" ");
		if("java.util.Date".equals(this.type)){
			sb.append("to_date(‘").append(this.value).append("‘,‘yyyy-MM-dd‘)");
		}else if("java.lang.Number".equals(this.type)
				||this.condition.indexOf("in")>0){//TODO 需要按类型处理
			sb.append(this.value);
		}else{
			sb.append("‘").append(this.value).append("‘");//TODO 需要处理特殊字符
		}
		return sb.toString();
	}
}
后台解析处理代码,修改org.jeecgframework.core.extend.hqlsearch.HqlGenerateUtil:
	public static void installHql(CriteriaQuery cq, Object searchObj,
			Map<String, String[]> parameterMap) {
		installHqlJoinAlias(cq, searchObj, getRuleMap(), parameterMap, "");
//		--增加一个特殊sql参数处理----------------------------------
		try{			if(StringUtil.isNotEmpty(parameterMap.get("_sqlbuilder"))){
				List<QueryCondition> list  = JSONHelper.toList(
						parameterMap.get("_sqlbuilder")[0]
			             , QueryCondition.class);
				String sql=getSql(list,"");
				System.out.println("DEBUG sqlbuilder:"+sql);
				cq.add(Restrictions.sqlRestriction(sql));
			}
		}catch(Exception e){
			e.printStackTrace();
		}
//		--增加一个特殊sql参数处理----------------------------------
		cq.add();
	}

五、实现约束

1)只支持标准命名的表名,因为是通过java驼峰命名转换带下划线的数据库表名,如果表名不是这个规则字段名会转换错误;
        2)Sql前端界面在输入时并没有做太多约束和控制,因此非专业用户使用时会出现非法的语句而查询无果,建议在懂sql的人员指导下使用不要直接交给用户。

 六、标签使用

Datagrid标签中已经对高级查询器做了封装,js变量也根据每个模块的id做了命名处理防止冲突。

使用时只需在datagrid标签加一个属性queryBuilder="true",例如

    <t:datagrid name="jeecgDemoList" title="DEMO示例列表" 
    autoLoadData="true" actionUrl="jeecgDemoController.do?datagrid" 
    sortName="userName" fitColumns="true"
	idField="id" fit="true" queryMode="group" checkbox="true" 
        queryBuilder="true">

模块UI效果如下,重置后面会多一个按钮:

七、TODO

  UI方面:易用性还可以提升,比如选中某字段和条件=时,值自动根据数据库表中该列实际值枚举一部分候选项;字段为date类型时,值编辑框变成date控件;字段为整形时,值编辑框有校验或只能输入整数的spinbox来防呆

  功能:List<QueryCondition>对象转换为sql getSql()函数中仅仅实现拼装原生sql,这块还有很大的改进空间,可以增加字段类型(int,string,date)的识别和处理、操作符(正则匹配)、内置表达式和函数(类似TFS)等扩展。

 安全:模块按钮还没有跟权限绑定,只是通过标签属性来开关,应该加一个动态权限由系统配置来控制

时间: 2024-10-11 17:59:12

Jeecg高级查询器的相关文章

优化jeecg底层高级查询,支持bool值和下拉框查询

最近在用jeecg做项目,在使用高级查询的时候发现它不支持布尔值的查询以及列表的下拉框的查询,所以小编修改了底层代码,完善了高级查询,现在与大家一起分享.先上一张图给大家看一下修改前的高级查询. 它只支持了文本的查询以及日期格式的查询,很难满足在使用过程中的要求.所以小编把他的功能丰富了一下,下面把源码分享给大家. 首先先简单介绍一下jeecg高级查询的原理,一切的秘密都在DataGridTag这个标签类里面,在打开一个页面的时候,这个类会对页面的左右变迁进行初始化,以及对高级查询的页面进行构造

css3 media媒体查询器用法总结 兼容ie8以下的方法

总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. http://www.360doc.com/content/14/0704/06/10734150_391862769.shtml 准备工作1:设置Meta标签 首先我们在使用Media的时候需要先设置下面这段代码,来兼容移动设备的展示效果: 这段代码的几个参数解释: width = device-width:宽度等于当前设备的宽度 initial-scale:初始的缩放比例(默认设置为1.0) minimum-scale:允许

css3 media媒体查询器用法总结

css3 media媒体查询器用法总结 Author:owenhong2014-05-30 随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错了,如今淘宝,凡客,携程等等公司都已经在大胆的尝试了这项技术,并完美的应用在了自己的网站上了.再不更新知识你就老了.我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 准备工作1:设置Meta标签 首先我们在使用Media的时候

css3 media媒体查询器用法总结(转载)

用法及meta标签的使用及IE最新 随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错了,如今淘宝,凡客,携程等等公司都已经在大胆的尝试了这项技术,并完美的应用在了自己的网站上了.再不更新知识你就老了.我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 准备工作1:设置Meta标签 首先我们在使用Media的时候需要先设置下面这段代码,来兼容移动设备的展示效果: <m

CSS3 media媒体查询器的使用方法

最近几年随着响应式布局的发展,一次开发多次使用,自适应屏幕的响应式网站的需求越来越多.但是怎样使得网站能自适应屏幕呢?这里就需要提到一个css3里面新增的技术了-media媒体查询器. 那么什么是media媒体查询器呢? Media媒体查询器是CSS3新增的一个可以检测打开网站的终端的屏幕分辨率的技术. Media媒体查询器的使用方法大致如下: 1.设置一个meta标签如:   1 <meta name="viewport" content="width=device-

css3 media媒体查询器用法总结(附js兼容方法)

css3 media媒体查询器用法总结 标签: 随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错了,如今淘宝,凡客,携程等等公司都已经在大胆的尝试了这项技术,并完美的应用在了自己的网站上了.再不更新知识你就老了.我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 准备工作1:设置Meta标签 首先我们在使用Media的时候需要先设置下面这段代码,来兼容移动设备的展示

响应式设计的核心CSS技术Media(媒体查询器)

总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. <meta http-equiv="X-UA-Compatible" content="IE=edge"><!--兼容ie--><meta name="viewport" content="width=device-width, initial-scale=1"><!--得到媒体查询屏幕宽度,缩放比例--> 准备

SQL高级查询技巧

1.UNION,EXCEPT,INTERSECT运算符 A,UNION 运算符 UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表. 当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行.两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2. B, EXCEPT 运算符 EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表

Mybatis学习记录(四)--高级查询和缓存

这些都是连贯的学习笔记,所以有的地方因为之前都说过,所以也就没怎么写详细了,看不太明白的可以看看之前的笔记. 一.高级查询 高级查询主要是一对一查询,一对多查询,多对多查询 1.一对一查询 有用户和订单两个表,用户对订单是1对1查询.也就是订单中有一个外键是指向用户的. 先创建实体类: User.java public class User { private int id; private String username; private String password; private St