ibatis 動態對映

2021-08-29 14:58:55 字數 3104 閱讀 1071

在複雜查詢過程中,我們常常需要根據使用者的選擇決定查詢條件,這裡發生變化的並不只是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 動態對映

在複雜查詢過程中,我們常常需要根據使用者的選擇決定查詢條件,這裡發生變化的並不只是sql 中的引數,包括select 語句中所包括的字段和限定條件,都可能發生變化。典型情況,如在乙個複雜的組合查詢頁面,我們必須根據使用者的選擇和輸入決定查詢的條件組合。乙個典型的頁面如下 對於這個組合查詢頁面,根據使...

Ibatis (五) 動態對映

xml select id getusers parameterclass user resultmap get user result select id,name,fromt user dynamic prepend where isnotempty prepend and property n...

ibatis對映檔案配置

id 指定了操作id,之後我們可以在 中通過指定操作id 來執行此節點所定 義的操作,如 sqlmap.update updateuser user id設定使得在乙個配置檔案中定義兩個同名節點成為可能 兩個update節 點,以不同id區分 parameterclass 指 定 了操作所需的引數型...