论坛首页 Java企业应用论坛

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

浏览 37424 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-03-11  
Lucas Lee 写道

所以,问题在于,(以JDBC为例)条件值为空,则同时影响Prepared SQL和Parameter Setting两个部分,
即,条件值不为空,则select * from table where name=?, ps.setString(1,name);
否则:select * from table .


使用DynamicQuery 的话,这点不用担心。 因为我们都帮用户作了处理。

另外这个小工具当时设计的时候也是遵循一个原则:尽量减少侵入性。

这个小工具做的工作仅仅是代替 你那段 “自己拼装SQL和拼装params"的逻辑。别的什么也不做。

你得到的结果仅仅是一个过滤后的queryStr(HQL或者EQL或者SQL)以及相应的params。
对于JDBC,可能还多了一个小小的步骤,因为JDBC不象ORM框架那样提供通用的设置参数的接口:setParameter(Object..)

都是非常原始的setInt,setString等接口。
如果用户基于返回的params来在PrepareStatement上设置参数,则还需要繁琐的逻辑。
所以我们在JDBC上面多了一个接口:setParams(PrepareStatement pst) ,来帮助用户一步到位的设置参数。

0 请登录后投票
   发表时间:2007-03-11  
你这个和我那个 easyDataAccess比较类似
我那个是全写在xml文件里
支持一些常用的判断

http://fins.iteye.com/blog/52371

有机会大家可以交流一下 互相取长补短
0 请登录后投票
   发表时间:2007-03-11  
fins 写道
你这个和我那个 easyDataAccess比较类似
我那个是全写在xml文件里
支持一些常用的判断

http://fins.iteye.com/blog/52371

有机会大家可以交流一下 互相取长补短


感谢你也提供了这么一个类似的工具。
我看了你的sample。 很不错,小巧灵活。

不过和我们的小工具还有区别,我们遵循了这么几个原则:
1)尽量让用户在编写查询语句的时候,和编写他原生查询语言没有差异。
   除了标签,其他的内容就是直接可以拿来查询的SQL或者HQL/EQL。

2 )无缝的集成到用户的开发环境,比如 Spring JDBCTemplate,Hibernate,JPA 等等。
   

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

另外这个小工具当时设计的时候也是遵循一个原则:尽量减少侵入性。

这个小工具做的工作仅仅是代替 你那段 “自己拼装SQL和拼装params"的逻辑。别的什么也不做。


我想你在注意减少侵入性的同时,需要注意保持易用性。
Anyway,我的确不喜欢这样的嵌入标签或对等物的SQL语法。
0 请登录后投票
   发表时间:2007-03-11  
不是特别喜欢标签,尤其在程序里面要记一堆标签的情况。
StringBuffer hql = "select sample from Sample sample where 1 = 1";
hql.add(Sample.notNull("and foo = :foo", foo);
hql.add(Sample.gtZero("and bar >= :bar"), bar);

或者
StringBuffer hql = "select sample from Sample sample where 1 = 1";
Sampel sample = SampleFactory.create(vo);
hql.add(Sample.notNull("and foo = :foo", "foo");
hql.add(Sample.gtZero("and bar = :bar"), "bar.field");


至少这样有ide的assist写起来会方便一点。
0 请登录后投票
   发表时间:2007-03-11  
Lucas Lee 写道
firebody 写道

另外这个小工具当时设计的时候也是遵循一个原则:尽量减少侵入性。

这个小工具做的工作仅仅是代替 你那段 “自己拼装SQL和拼装params"的逻辑。别的什么也不做。


我想你在注意减少侵入性的同时,需要注意保持易用性。
Anyway,我的确不喜欢这样的嵌入标签或对等物的SQL语法。


哈哈,看来不同的人对同样东西的看法很不一样。对sql标注这个办法是firebody提出来的,我觉得太有想象力了,哈哈。
0 请登录后投票
   发表时间:2007-03-11  
firebody 写道
ajoo 写道
不错。
就是这些tag有些不太爽。 

可不可以这样?

直接写ql,

"select ... where name=:name and age=:age"。

然后parser把它翻译成ast。

下面,代码生成器根据参数的值来生成代码。

String query = ...;
HashMap params = new HashMap();
params.put("name", "tom");
String hql = codegen.generateHql(query, params);


因为:age参数为null,自然就把and age=:age这个子句去掉了。

这些tag看起来确实不大爽,不过除此之外,我还没有找到 能够满足用户“自定值”功能的 声明性的需求的其他方式。

像你提到的方式,确实是一个好的主意。 不过如果方便用户自定制条件进行过滤的话,估计也差不多走回我们的路子。

现在,我们的DynamicQuery已经提供了更简易的方式来进行配置处理。
看这个例子:

		String hql = "select o from User o where 1=1 <NOTNULL:name>and o.name1 = :name1 </NOTNULL:name>";
		DynamicQResult dr = qt.parse(hql).setProperties(vo).generate();


NOTNULL是预定义的基于Bean访问的断言,冒号后面的是bean的属性名称。
<NOTNULL:name>and o.name1 = :name1 </NOTNULL:name> 

这句话表示 如果bean的属性:name不为空 ,则这个条件被接受,参数也随之被接受。
参数的取值 按照paramName:name1来从bean取得。 bean就是用户通过setProperties传入的参数。
翻译为表述语言就是:
如果 bean.name不为空,则接受这个条件并且将bean.name1的值作为参数名为:name1的值。


此时,可能有些人比较反感频繁的写paramName,properName,对此,我们也提供更为简便的方式,例子:
String hql = "select o from User o where 1=1 <NOTNULL>and o.name = :name </NOTNULL>";
		DynamicQResult dr = qt.parse(hql).setProperties(vo).generate();


这个例子和前面的例子,差别在于NOTNULL后面不再跟着:name ,此时NOTNULL断言针对的属性值 就是
paramName ,也就是里面的参数名:name. 翻译为表述语言就是:

如果bean.name 不为空,则接受这个条件并且将bean.name作为参数:name的值 。

前面的两个例子,总是以命名参数作为查询的参数,有些人反对了,”我喜欢用占位参数阿“,对占位符形式的查询,我们也提供了简便的支持,例子:
String hql = "select o from User o where 1=1 <NOTNULL:name>and o.name = ? </NOTNULL:name>";
		DynamicQResult dr = qt.parse(hql).setProperties(vo).generate();


参数占位符: ? 对应的参数值默认就是 根据接受条件里面的属性名:name .

这些渐变的方式,能够大大方便用户的使用.

形似:NOTNULL,NOTEMPTYSTR,GTZERO 这些特殊的符号 我们称之为 “预定义断言”,
这种断言用户完全可以自己定制使用。


两点想法:
1。自定义断言的需求是否频繁到值得去影响不需要预定义断言的那大部分用户的易用性?可不可以考虑只处理90%的一般情况?(就象rails干脆不支持复合key一样?)
2。这个自定义断言难道不能在参数值上下功夫?毕竟sql最好保持sql,逻辑还是在java里为妙。比如:
String hql = "select o from User o where o.name = $name";
HashMap params = new HashMap();
params.put("name", notEmptyStr(name));
DynamicQResult dr = qt.generate(hql, params);


让notEmptyStr在string为空的时候返回null或者一个你们自己特定的Null Object可行么?
0 请登录后投票
   发表时间:2007-03-12  
这是我的拼装,定义了userslist,把页面直接扔给FilterAction就OK了。无需再写代码
<querylist name="userslist" title="系统用户查询" >
<bean_ref bean="user" name="user"/>
<id name="id" datatype="int" hidden="true"/>
<listfields value="organdbid,loginid,username,describe,state"/>
<filter hql=" [organdbid =rgandbid] and [loginid like :loginid] and [username like :username] and [state = :state]" >
<parameter name="organdbid" hqltype="long" model="true"/>
<parameter name="loginid" hqltype="string" op="like" model="true"/>
<parameter name="username" hqltype="string" op="like" model="true"/>
<parameter name="state" hqltype="string"  model="true"/>
</filter>
<order property="organdbid,loginid" asc="asc"/>
    </querylist>
0 请登录后投票
   发表时间:2007-03-12  
俺也来一个,献丑了,与ibatis类似
http://www.iteye.com/topic/40143
0 请登录后投票
   发表时间:2007-03-12  
以前不知是哪位已经贡献了很完美的解决方法了就是:
SQL= where (:a is not null and :a=xxx ) and/or (:b is not null and :b=xxx) ...
Code = new Object[]{model.getA(),model.getB()...}
0 请登录后投票
论坛首页 Java企业应用版

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