badqiu

          XPer
          隨筆 - 46, 文章 - 3, 評(píng)論 - 195, 引用 - 0
          數(shù)據(jù)加載中……

          動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明

          特性列表:

          1. 動(dòng)態(tài)構(gòu)造sql條件語(yǔ)句,提供sql拼接與使用占位符兩種方式
          2. 數(shù)據(jù)類(lèi)型的修飾
          3. 對(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宣傳一下,本工具也集成在里面
          rapid-framework簡(jiǎn)介:
          一個(gè)類(lèi)似 ruby on rails 的java web快速開(kāi)發(fā)腳手架,本著不重復(fù)發(fā)明輪子的原則,框架只是將零散的struts(struts2)+spring+hibernate各個(gè)組件組裝好在一起,并對(duì)struts及struts2進(jìn)行改造,提供零配置編程,并內(nèi)置一個(gè)強(qiáng)大的代碼生成器及模板文件, 可以生成java的hibernat model,dao,manager,struts+struts2 action類(lèi),可以生成jsp的增刪改查及列表頁(yè)面

          快速演示視頻下載
          代碼生成器生成的增刪改查截圖

          posted on 2008-08-07 09:26 badqiu 閱讀(3670) 評(píng)論(12)  編輯  收藏

          評(píng)論

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

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

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          where 1=1 真tmd的搞笑,這年頭居然還有這種人~
          2008-08-07 13:09 | po

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明[未登錄](méi)  回復(fù)  更多評(píng)論   

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

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          好東西,非常感謝
          @po
          可以不同意,請(qǐng)不要出言不遜,這不是技術(shù)人員討論問(wèn)題的方式。你可以做出更好的東西show一下啊
          2008-08-07 13:27 | xihuyu2000

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          outputFile


          2008-08-07 14:43 | wdd

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          @po
          where 1=1可以避免很多繁瑣的判斷,而且SQL server在優(yōu)化時(shí)會(huì)直接將這句話去掉,不會(huì)有什么性能影響。
          2008-08-07 18:59 | lijin

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          跟ibatis比,性能優(yōu)多少?
          有測(cè)試過(guò)不?

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

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明[未登錄](méi)  回復(fù)  更多評(píng)論   

          十萬(wàn)條下面的語(yǔ)句循環(huán)構(gòu)造,差不多7,8秒吧,具體可以看XsqlBuilderTest.testPerformence();
          性能問(wèn)題可以忽略不計(jì)

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

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明[未登錄](méi)  回復(fù)  更多評(píng)論   

          10萬(wàn)條循環(huán):
          [PerformenceTest],count:100000 costTime:2406ms
          2008-08-08 10:36 | badqiu

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          where 1=1這句是必須的,你用過(guò)就知道了。少了有時(shí)會(huì)報(bào)錯(cuò)!
          2009-06-05 21:02 | 事實(shí)上

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          性能問(wèn)題應(yīng)該不是主要的,不必過(guò)多注意
          2011-10-17 03:41 | 注冊(cè)公司

          # re: 動(dòng)態(tài)構(gòu)造sql的利器:rapid-xsqlbuider詳細(xì)說(shuō)明  回復(fù)  更多評(píng)論   

          請(qǐng)問(wèn)時(shí)間怎么查詢(xún)
          2015-10-26 23:57 | 林曉升

          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 康乐县| 霸州市| 太仓市| 方山县| 纳雍县| 北川| 当涂县| 宾阳县| 新龙县| 木兰县| 峡江县| 南京市| 建德市| 科尔| 南澳县| 无锡市| 长顺县| 桂林市| 开原市| 保山市| 吉水县| 陆川县| 宁夏| 自治县| 敦化市| 河源市| 柞水县| 垣曲县| 齐齐哈尔市| 商洛市| 运城市| 永和县| 高阳县| 中阳县| 元氏县| 工布江达县| 榕江县| 巴南区| 武汉市| 凤凰县| 陈巴尔虎旗|