動態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說明
特性列表:
- 動態(tài)構(gòu)造sql條件語句,提供sql拼接與使用占位符兩種方式
- 數(shù)據(jù)類型的修飾
- 對SQL注入攻擊的防范
問題:
手工構(gòu)造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判斷導(dǎo)致sql語句不清晰,我們再來看下rapid-xsqlbuilder的做法
rapid-xsqlbuilder構(gòu)造SQL例子
示例:
?1?//?清晰的sql語句,/~?~/為一個語法塊
?2??String?sql=?"select?*?from?user?where?1=1?"?
?3??????????+?"/~?and?username?=?{username}?~/"???
?4??????????+?"/~?and?password?=?{password}?~/";???
?5??
?6??//?filters為參數(shù)
?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不存在而沒有被構(gòu)造出來filters過濾: sex
filters中由于沒有類似/~ sex={sex} ~/ 這一段,所以在過濾完的filters中不存在最終構(gòu)造生成的結(jié)果
HQL: XsqlFilterResult.xsql屬性??????????
select * from user where 1=1 and username=:username??
???????
構(gòu)造后返回的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] ~/數(shù)據(jù)據(jù)類型修飾
將Map filters中的數(shù)據(jù)類型修飾為另外一種類型
/~ {username} ~/
/~ {age?int} ~/
/~ {birthDate?timestamp(yyyy年MM月dd日)} ~/中括號[]與大括號{}的區(qū)別
中括號會直接替換為其值,用于拼接SQL
在XsqlFilterResult.getAcceptedFilters()中不會存在該key的值
如 /~ username like '%[username]%' ~/,如果filters中username=badqiu
則會生成: username like '%badqiu%'大拓號只是起到標(biāo)記作用,用于占位符
原始方法是XsqlBuilder.applyFilters(sql,filters);
如"/~ and username = {username} ~/",過濾完還是為 and username = {username}
但在這時我們使用將{username}替換為HQL的:username或是SQL的?號
SQL注入攻擊的防范
問題:
拼接的SQL如果不對單引號(有些數(shù)據(jù)庫有反斜杠)進(jìn)行過濾,則會存在SQL注入攻擊問題解決:
使用SafeSqlProcesser,進(jìn)行sql過濾1?XsqlBuilder?builder?=?new?XsqlBuilder(SafeSqlProcesserFactory.getMysql());SafeSqlProcesser其中的一個源碼分析
1?/**
2??*?過濾單個單引號為雙引號的SafeSqlFilter<p>
3??*?適用數(shù)據(jù)庫(MS?SqlServer,Oracle,DB2)
4??*/
5?public?String?process(String?value)?{
6?????if(value?==?null)?return?null;
7?????return?value.replaceAll("'",?"''");?//?Mysql還需過濾反斜框
8?}
9?
最后不忘為rapid-framework宣傳一下,本工具也集成在里面