论坛首页 Java企业应用论坛

介绍DynamicQueryTool,一个用于解决“拼装动态查询”的小工具。

浏览 37429 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-03-13  
感觉还是麻烦了一些,如果能更简化一些的话更好
0 请登录后投票
   发表时间:2007-03-13  
ajoo 写道
firebody 写道

不过,有些问题:
<count>select count(*)</count><list>select o</list> From User o .....

比如上面,因为希望可以重用后面的查询条件,所以放到了一起,通过标签 count,list来选择过滤,如果不使用标签,有什么更好的方式吗?
另外,如果ajoo你感兴趣和有空的话,也欢迎你加入进来,实现你自己想要的特性阿。 嘿嘿


这种东西我是认为应该用jrc来解决的。直接把字符串放在一起反而很不自然。
Relation base = parse("select * from User o ...");
Relation query = base.project(useCount?"count(*)":"o");


或者就是直接字符串拼接也好啊。

我倒是挺感兴趣加入的。如果咱们能对设计取得一定的共识的话。我的想法是把jrc的parser扒过来,然后处理这个ast。或者把jrc和你的项目合并也行。(不过jrc的parser用比较严格的sql-92语法,不支持"from a,b,c"这种。不知道是否有必要花精力增加对这个语法的支持)

用jrc分析字符串,然后采用你说的方式进行处理的话,应该能很好得实现你所说的需求。
不过我担心一个问题:

* 特定于我们要解决的需求,这样做是否在实现的复杂度上大了些?我们原来采用的方式是:不用分析用户的除了标签之外的内容语意,也就意味着不用受限于复杂的parser以及对各种各样的查询语言提供更为广泛的支持。 当然,我们存在一种共识:用户应该有责任保证除了标签以外的内容是合法的查询语言。

0 请登录后投票
   发表时间:2007-03-13  
firebody 写道

用jrc分析字符串,然后采用你说的方式进行处理的话,应该能很好得实现你所说的需求。
不过我担心一个问题:

* 特定于我们要解决的需求,这样做是否在实现的复杂度上大了些?我们原来采用的方式是:不用分析用户的除了标签之外的内容语意,也就意味着不用受限于复杂的parser以及对各种各样的查询语言提供更为广泛的支持。 当然,我们存在一种共识:用户应该有责任保证除了标签以外的内容是合法的查询语言。


说的没错。jrc的难点在于parser。不同的dbms的sql语法不完全一样。hql和sql的语法也不完全一样。而要真正实现比较聪明点的sql模板,不parse又是不行的。所以jrc才采取了parse一个统一的标准语法,然后翻译成各种sql dialect的方案。

不过,对这个dynamic query的工具来说,似乎不需要这样,直接parse目标sql就可以。而且为了简单还可以限制一下sql的写法。比如不许写"from a,b,c",而是必须用sql-92语法。

对了,你的这个tag的方式虽然不需要parse,但是怎么处理sql里面带有"where tag='</name>'"这种特殊query的?
0 请登录后投票
   发表时间:2007-03-13  
ajoo 写道
firebody 写道

用jrc分析字符串,然后采用你说的方式进行处理的话,应该能很好得实现你所说的需求。
不过我担心一个问题:

* 特定于我们要解决的需求,这样做是否在实现的复杂度上大了些?我们原来采用的方式是:不用分析用户的除了标签之外的内容语意,也就意味着不用受限于复杂的parser以及对各种各样的查询语言提供更为广泛的支持。 当然,我们存在一种共识:用户应该有责任保证除了标签以外的内容是合法的查询语言。


说的没错。jrc的难点在于parser。不同的dbms的sql语法不完全一样。hql和sql的语法也不完全一样。而要真正实现比较聪明点的sql模板,不parse又是不行的。所以jrc才采取了parse一个统一的标准语法,然后翻译成各种sql dialect的方案。

不过,对这个dynamic query的工具来说,似乎不需要这样,直接parse目标sql就可以。而且为了简单还可以限制一下sql的写法。比如不许写"from a,b,c",而是必须用sql-92语法。

对了,你的这个tag的方式虽然不需要parse,但是怎么处理sql里面带有"where tag='</name>'"这种特殊query的?


我们设计比较简单,就是采用正则表达式匹配标签。用group分组出需要的内容。
你上面提到的case,正则表达式在处理这个的时候,确实会混淆,当时我们想到几个解决办法:
1) 因为是用户自定义标签标识,所以需要用户保证 标签 不能够和 “常量字符串”内的字符有混淆的地方。
    比如你上面提到</name> ,意味着用户不能使用tag:<name>
2)更复杂的正则表达式来 过滤常量字符串里面的标签 。
3)因为可能出现和 tag混淆的地方都是来自于常量字符串,可以先把常量字符串 替换为 空字符串。比如你上面的 "</name",替换成"" 。然后作相应标签的匹配。

现在,我们选择了1),让用户自己保证标签 不和 常量字符串内的字符混淆。
0 请登录后投票
   发表时间:2007-03-13  
直接写存储过程得了。这样调用起来就一个callStatement就可以了,更简单
另外一个思路:把所有的sql拼接放到一个文本里,例如:
----queryUser.txt-------
select * from User where loginDate<sysdate-1
if :name present then and name=:name
if :department present then and  department=:department

或者有简化形势
select * from User where loginDate<sysdate-1
ifp  name=:name
ifp  department=:department

这好处是开发人员和数据库人员都能理解和看懂

Javad代码也容易:
DynamicQueryTool tool = new DynamicQueryTool ("queryUser.txt");

Query q = tool.setParameter(paraMap);
List user = q.list();

至于为什么推荐写道文本里(但并不反对作为一个String变量),是因为可以方便人看,以及如果有人提供调适工具,那很容易江文本作为输入进行Sql调试

0 请登录后投票
   发表时间:2007-03-13  
关于 count 的重用, 偶尔想起了, 其实不必在整个 sql 语句上下功夫呀, DQ只生成 FROM 以后的内容就好了:

count 的时候 用 "select count(*) " + DQ.genSQL();

读取的时候用 "select * " + DQ.genSQL();

谨供参考.
0 请登录后投票
   发表时间:2007-03-13  
complystill 写道
关于 count 的重用, 偶尔想起了, 其实不必在整个 sql 语句上下功夫呀, DQ只生成 FROM 以后的内容就好了:

count 的时候 用 "select count(*) " + DQ.genSQL();

读取的时候用 "select * " + DQ.genSQL();

谨供参考.


这确实属于用户喜好的一个选择。
不过,后面还有根据count,list的不同选择:group by ,order by 部分呢。

既然提供了根据标签过滤得功能,何不都放到里面去?

不然,也都可以 类似这样了:
"select *" + dq.getSql()+"group by"  +....

0 请登录后投票
   发表时间:2007-03-13  
删除。 (因为重发)
0 请登录后投票
   发表时间:2007-03-15  
非常感兴趣!结果跑到 sf 上一看,一个文件都没有。
0 请登录后投票
   发表时间:2007-03-15  
你这种方式还是太麻烦了,我也写了一个工作类,也是用来处理动态参数的,方式类似下面
	    String hql="select a from AllImpDxjl a where 1=1 and a.dwdm=$ and a.jszh=$ and a.jdsh=$ and a.jdjg=$ and a.dabh=$ and a.fzjg=$";
	    Jbq jbq=new Jbq(hql);
	    jbq.setStringBet(1, downDataForm.getDwdm());
	    jbq.setStringBet(2, downDataForm.getJszh());
	    jbq.setStringBet(3, downDataForm.getJdsh());
	    jbq.setStringBet(4, downDataForm.getJdjg());
	    jbq.setStringBet(5, downDataForm.getDabh());
	    jbq.setStringBet(6, downDataForm.getFzjg());
这样当downDataForm.getDwdm()为空值时,上面的hql中的a.dwdm=$为变成空的,就会变成
select a from AllImpDxjl a where 1=1 and a.jszh=$ and a.jdsh=$ and a.jdjg=$ and a.dabh=$ and a.fzjg=$
以此类推。。。。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics