ibatis 動態查詢

2021-09-01 08:36:38 字數 3342 閱讀 1504

在複雜查詢過程中,我們常常需要根據使用者的選擇決定查詢條件,這裡發生變化的

並不只是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...