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