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?==?null)?return?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 閱讀(3670) 評論(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 | 林曉升

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 台安县| 宜春市| 崇仁县| 赣州市| 苗栗市| 翁牛特旗| 南川市| 海南省| 宁陵县| 穆棱市| 哈尔滨市| 团风县| 额济纳旗| 贡觉县| 柘荣县| 寿宁县| 清原| 安乡县| 盘山县| 隆德县| 黎川县| 元朗区| 吉林市| 金川县| 台湾省| 萝北县| 华容县| 志丹县| 乐都县| 东辽县| 喀喇沁旗| 祁阳县| 远安县| 黎平县| 贵港市| 长垣县| 靖宇县| 宝坻区| 哈密市| 郸城县| 吕梁市|