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

特性列表:

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

问题:

手工构造SQL语句的情况

<a name="xsqlbuilder-%E9%97%AE%E9%A2%98%3A" data-cke-saved-name="xsqlbuilder-%E9%97%AE%E9%A2%98%3A"><span style="color:#000000"> </span></a>

Java代码 复制代码 收藏代码

  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. }  
String sql = "select * from user where 1=1 ";
String user_id = (String)filters.get("user_id");
if( user_id != null && user_id.length() > 0) {
   sql = sql + " and user_id = " + user_id;
}
String age = (String)filters.get("age");
if(age != null && age.length() > 0) {
   sql = sql + " and age > " + age;
}

 

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

rapid-xsqlbuilder构造SQL例子

示例:

Java代码 复制代码 收藏代码

  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());  
// 清晰的sql语句,/~ ~/为一个语法块
 String sql= "select * from user where 1=1 " 
         + "/~ and username = {username} ~/"   
         + "/~ and password = {password} ~/";   
 
 // filters为参数
 Map filters = new HashMap();   
 filters.put("username", "badqiu"); 
 filters.put("sex", "F");  
 
 XsqlFilterResult result = new XsqlBuilder().generateHql(sql,filters);
 
 assertTrue(result.getAcceptedFilters().containsKey("username"));
 assertFalse(result.getAcceptedFilters().containsKey("sex"));
 assertEquals("select * from user where 1=1  and username = :username ", result.getXsql());

 

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

被过滤掉的东西:

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

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

最终构造生成的结果

HQL: XsqlFilterResult.xsql属性

<a name="xsqlbuilder-%E6%9C%80%E7%BB%88%E6%9E%84%E9%80%A0%E7%94%9F%E6%88%90%E7%9A%84%E7%BB%93%E6%9E%9C" data-cke-saved-name="xsqlbuilder-%E6%9C%80%E7%BB%88%E6%9E%84%E9%80%A0%E7%94%9F%E6%88%90%E7%9A%84%E7%BB%93%E6%9E%9C">select * from user where 1=1 and username=:username</a>

构造后返回的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过滤

Java代码 复制代码 收藏代码

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

 

SafeSqlProcesser其中的一个源码分析

Java代码 复制代码 收藏代码

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

 

Project Home: http://code.google.com/p/rapid-xsqlbuilder/

最后不忘为rapid-framework宣传一下,本工具也集成在里面

rapid-framework简介:

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值