在複雜查詢過程中,我們常常需要根據使用者的選擇決定查詢條件,這裡發生變化的
並不只是sql 中的引數,包括select 語句中所包括的字段和限定條件,都可能發生變
化。典型情況,如在乙個複雜的組合查詢頁面,我們必須根據使用者的選擇和輸入決定查
詢的條件組合。
乙個典型的頁面如下:
對於這個組合查詢頁面,根據使用者選擇填寫的內容,我們應為其生成不同的查詢語
句。如使用者沒有填寫任何資訊即提交查詢請求,我們應該返回所有記錄:
select * from t_user;
如使用者只在頁面上填寫了姓名「erica」,我們應該生成類似:
select * from t_user where name like 『%erica%』 ;
的sql查詢語句。
select * from t_user where address like 『%beijing%」;
的sql。
select * from t_user where name like 『%erica%』 and address like 『%beijing%」
的sql查詢語句。
對於ibatis 這樣需要預先指定sql 語句的orm 實現而言,傳統的做法無非通過
if-else 語句對輸入引數加以判定,然後針對使用者選擇呼叫不同的statement 定義。對於
上面這種簡單的情況(兩種查詢條件的排列組合,共4 種情況)而言,statement 的重
復定義工作已經讓人不厭其煩,而對於動輒擁有七八個查詢條件,乃至十幾個查詢條件
的排列組合而言,瑣碎反覆的statement定義實在讓人不堪承受。
考慮到這個問題,ibatis引入了動態對映機制,即在statement定義中,根據不同的
查詢引數,設定對應的sql語句。
還是以上面的示例為例:
select
id,name,
***from t_user
(name like #name#)
(address like #address#)
通過dynamic 節點,我們定義了乙個動態的where 子句。此where 子句中將
可能包含兩個針對name 和address 欄位的判斷條件。而這兩個字段是否加入檢索取決
於使用者所提供的查詢條件(字段是否為空[isnotempty])。
對於乙個典型的web程式而言,我們通過httpservletrequest獲得表單中的欄位名
並將其設入查詢引數,如:
user.setname(request.getparameter("name"));
user.setaddress(request.getparameter("address"));
sqlmap.queryforlist("user.getusers", user);
在執行queryforlist("user.getusers", user)時,ibatis 即根據配置文
件中設定的sql動態生成規則,建立相應的sql語句。
上面的示例中,我們通過判定節點isnotempty,指定了關於name 和address 屬
性的動態規則:
(name like #name#)
這個節點對應的語義是,如果引數類的"name"屬性非空(isnotempty,即非空
字串」」),則在生成的sql where字句中包括判定條件(name like #name#),其
中#name#將以引數類的name屬性值填充。
address屬性的判定生成與name屬性完全相同,這裡就不再贅述。
這樣,我們通過在statement 定義中引入dynamic 節點,很簡單的實現了sql 判
定子句的動態生成,對於複雜的組合查詢而言,這將帶來極大的便利。
判定節點的定義可以非常靈活,我們甚至可以使用巢狀的判定節點來實現複雜的動
態對映,如:
( name=#name#
address=#address#
)這段定義規定,只有使用者提供了姓名資訊時,才能結合位址資料進行查詢(如果只
提供位址資料,而將姓名資訊忽略,將依然被視為全檢索)。
dynamic節點和判定節點中的prepend屬性,指明了本節點中定義的sql子句在
主體sql中出現時的字首。
如:(name like #name#)
(address like #address#)
假設"name"屬性的值為「erica」, "address"屬性的值為「beijing」,則會
生成類似下面的sql子句(實際執行期將生成帶佔位符的preparedstatement,之
後再為其填充資料):
where (name like 『beijing』) and (address like 『beijing』)
其中where 之後的語句是在dynamic 節點中所定義,因此以dynamic 節點的
prepend設定("where")作為字首,而其中的」and」,實際上是address屬性所對
應的isnotempty節點的prepend設定,它引領了對應節點中定義的sql子句。至於
name屬性對應的isnotempty節點,由於ibatis會自動判定是否需要追加prepend
字首,這裡(name like #name#)是where 子句中的第乙個條件子句,無需and 前
綴,所以自動省略。
判定節點並非僅限於isnotempty,ibatis中提供了豐富的判定定義功能。
判定節點分兩類:
ø 一元判定
一元判定是針對屬性值本身的判定,如屬性是否為null,是否為空值等。
上面示例中isnotempty就是典型的一元判定。
一元判定節點有:
節點名 描述
引數類中是否提供了此屬性
與相反屬性值是否為null
與相反如果屬性為collection或者string,其size是否<1,
如果非以上兩種型別,則通過
string.valueof(屬性值)
獲得其string型別的值後,判斷其size是否<1
與相反。
ø 二元判定
二元判定有兩個判定引數,一是屬性名,而是判定值,如
(age=#age#)
其中,property="age"指定了屬性名」age」,comparevalue=」18」指明
了判定值為」18」。
上面判定節點isgreaterthan 對應的語義是:如果age 屬性大於
18(comparevalue),則在sql中加入(age=#age#)條件。
二元判定節點有:
節點名 屬性值與comparevalues的關係
相等。不等。
大於大於等於
小於小於等於
ibatis 動態查詢
最近專案需要,做了乙個動態查詢。把查詢結果返回到頁面上顯示。要查詢的字段和表名都是動態的,是在後台拼出來的。可是在ibatis中執行的時候總報 列名無效 在sql plus中執行則正常。百思不得其解。後來通過查資料,解決如下 select t.creator,t.create dt,decode o...
ibatis動態字段查詢
想要動態的獲取所需要的字段,想來想去沒有想到好的方法,只有下面乙個不成熟的想法,提筆記之,以備改進。極其簡單,一看即明白。有一點要注意的就是remapresults true 一定要設定 快取是把雙刃劍 entity.getfeild map put partner id partner id en...
ibatis的動態查詢
該文是對ibatis2開發指南中動態對映章節的總結 參考下面典型查詢畫面 查詢條件有姓名和位址,二者都有為空的可能,如果採用傳統的方式,可能需要做下面的查詢語句 select from t user select from t user where name like erica select fr...