badqiu

XPer
随笔 - 46, 文章 - 3, 评论 - 195, 引用 - 0
数据加载中……

动态构造sql的利器:rapid-xsqlbuider详细说明

特性列表:

  1. 动态构造sql条件语句,提供sql拼接与使用占位符两种方式
  2. 数据类型的修饰
  3. 对SQL注入攻击的防范

问题:

手工构造SQL语句的情况

										
1 String sql = "select * from user where 1=1 ";
2 String user_id = (String)filters.get("user_id");
3 if( user_id != null && user_id.length() > 0) {
4    sql = sql + " and user_id = " + user_id;
5 }
6 String age = (String)filters.get("age");
7 if(age != null && age.length() > 0) {
8    sql = sql + " and age > " + age;
9 }

过多的if判断导致sql语句不清晰,我们再来看下rapid-xsqlbuilder的做法

rapid-xsqlbuilder构造SQL例子

示例:

 1 // 清晰的sql语句,/~ ~/为一个语法块
 2  String sql= "select * from user where 1=1 " 
 3          + "/~ and username = {username} ~/"   
 4          + "/~ and password = {password} ~/";   
 5  
 6  // filters为参数
 7  Map filters = new HashMap();   
 8  filters.put("username""badqiu"); 
 9  filters.put("sex""F");  
10  
11  XsqlFilterResult result = new XsqlBuilder().generateHql(sql,filters);
12  
13  assertTrue(result.getAcceptedFilters().containsKey("username"));
14  assertFalse(result.getAcceptedFilters().containsKey("sex"));
15  assertEquals("select * from user where 1=1  and username = :username ", result.getXsql());
16 

XsqlFilterResult为处理完返回的东西,包含两个属性xsql,acceptedFilters

被过滤掉的东西:

SQL过滤: /~ and password = {password} ~/
这一段由于在filters中password不存在而没有被构造出来

filters过滤: sex
filters中由于没有类似/~ sex={sex} ~/ 这一段,所以在过滤完的filters中不存在

最终构造生成的结果

HQL: XsqlFilterResult.xsql属性          
select * from user where 1=1 and username=:username  
       
构造后返回的Map filters: XsqlFilterResult.acceptedFilters 属性
username=badqiu

语法

语法

/~ {key} ~/
/~ [key] ~/
/~ {key_1} [key_2] ... {key_3} ~/
/~ {key?modifier} ~/
/~ {key?modifier(arg1,arg2) ~/
/~ {key?modifier?modifier?...?modifier} ~/

示例:

/~ username = {username} ~/
/~ password like '%[password]%' ~/
/~ birthDate > {startBirthDate} and birthDate < [endBirthDate] ~/

数据据类型修饰

将Map filters中的数据类型修饰为另外一种类型

/~ {username} ~/
/~ {age?int} ~/
/~ {birthDate?timestamp(yyyy年MM月dd日)} ~/

中括号[]与大括号{}的区别

中括号会直接替换为其值,用于拼接SQL
在XsqlFilterResult.getAcceptedFilters()中不会存在该key的值
如 /~ username like '%[username]%' ~/,如果filters中username=badqiu
则会生成: username like '%badqiu%'

大拓号只是起到标记作用,用于占位符
原始方法是XsqlBuilder.applyFilters(sql,filters);
如"/~ and username = {username} ~/",过滤完还是为 and username = {username}
但在这时我们使用将{username}替换为HQL的:username或是SQL的?号

SQL注入攻击的防范

问题:
拼接的SQL如果不对单引号(有些数据库有反斜杠)进行过滤,则会存在SQL注入攻击问题

解决:
使用SafeSqlProcesser,进行sql过滤

										
1 XsqlBuilder builder = new XsqlBuilder(SafeSqlProcesserFactory.getMysql());

SafeSqlProcesser其中的一个源码分析

										
1 /**
2  * 过滤单个单引号为双引号的SafeSqlFilter<p>
3  * 适用数据库(MS SqlServer,Oracle,DB2)
4  */
5 public String process(String value) {
6     if(value == nullreturn null;
7     return value.replaceAll("'""''"); // Mysql还需过滤反斜框
8 }
9 





最后不忘为rapid-framework宣传一下,本工具也集成在里面
rapid-framework简介:
一个类似 ruby on rails 的java web快速开发脚手架,本着不重复发明轮子的原则,框架只是将零散的struts(struts2)+spring+hibernate各个组件组装好在一起,并对struts及struts2进行改造,提供零配置编程,并内置一个强大的代码生成器及模板文件, 可以生成java的hibernat model,dao,manager,struts+struts2 action类,可以生成jsp的增删改查及列表页面

快速演示视频下载
代码生成器生成的增删改查截图

posted on 2008-08-07 09:26 badqiu 阅读(3661) 评论(12)  编辑  收藏

评论

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

好东西!支持!
2008-08-07 12:41 | R_XiaoGuang

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

where 1=1 真tmd的搞笑,这年头居然还有这种人~
2008-08-07 13:09 | po

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明[未登录]  回复  更多评论   

@po
但不知你还有其它更好的办法?
2008-08-07 13:13 | badqiu

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

好东西,非常感谢
@po
可以不同意,请不要出言不逊,这不是技术人员讨论问题的方式。你可以做出更好的东西show一下啊
2008-08-07 13:27 | xihuyu2000

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

outputFile


2008-08-07 14:43 | wdd

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

@po
where 1=1可以避免很多繁琐的判断,而且SQL server在优化时会直接将这句话去掉,不会有什么性能影响。
2008-08-07 18:59 | lijin

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

跟ibatis比,性能优多少?
有测试过不?

如果性能差距不大,我情愿选择ibatis
2008-08-07 20:34 | galaxystar

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明[未登录]  回复  更多评论   

十万条下面的语句循环构造,差不多7,8秒吧,具体可以看XsqlBuilderTest.testPerformence();
性能问题可以忽略不计

"select * from user where 1=1"
+"/~ and username = {username}~/"
+"/~ and pwd = '[password]'~/"
+"/~ and age = {age}~/";
2008-08-07 22:05 | badqiu

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明[未登录]  回复  更多评论   

10万条循环:
[PerformenceTest],count:100000 costTime:2406ms
2008-08-08 10:36 | badqiu

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

where 1=1这句是必须的,你用过就知道了。少了有时会报错!
2009-06-05 21:02 | 事实上

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

性能问题应该不是主要的,不必过多注意
2011-10-17 03:41 | 注册公司

# re: 动态构造sql的利器:rapid-xsqlbuider详细说明  回复  更多评论   

请问时间怎么查询
2015-10-26 23:57 | 林晓升

只有注册用户登录后才能发表评论。


网站导航: