天天看點

Mybatis - 動态sql1.if2.choose

learn from:http://www.mybatis.org/mybatis-3/dynamic-sql.html

mybatis支援動态拼接sql語句。主要有:

<a href="#if">if</a>

choose (when, otherwise)

trim (where, set)

foreach

首先看基本執行個體:

這裡遇到一個問題:

也就是說,mybatis将name當做輸入參數的一個屬性,并且期望通過getter方法來擷取它的值。很容易想到,将輸入參數改成Blog就可以了。

然而,這并不符合我們的查詢習慣,比如,如果是Blog就必須這樣查詢:

第一種做法是簡單類型都是使用_parameter來代替。

第二種做法比較容易了解,在方法參數前添加@Param(value="xxx")注解來使用xxx作為傳入參數。

兩種做法均可,是以,看你喜歡了,是想要省事簡潔還是通俗易讀。在這裡,還是選擇第0種方案,即傳入Blog對象來作為查詢條件。

if節點中,屬性test是一個boolean值,為true的時候将拼接if裡的sql語句。

參數值是可以包含一些掩碼或通配符的.比如通配符%和占位符_

是以,很簡單很容易了解。

首先看期望的結果,blog表中有三條滿足name like:

這三條中,滿足author的username like的有兩條:

也就是我們最終希望結果是blog id為8 和 9。

mybatis的sql語句如下:

當blog的name不為null的時候查詢name比對,當author的username不為null的時候,查詢author的username比對。

第一個if節點的test為name,這個會查找Blog的name字段,如果傳入參數Blog沒有name字段,那麼就會像我們開始那樣報錯。是以,name必須是blog的一個字段。同理,#{name}這個也要和blog字段字面量的值比對。

第二個if節點的test裡看到了and,and就是并且。首先判斷author是否為null,就是判斷Blog對象的author屬性是否為null。接着判斷author.name是否為null,這裡就有點問題了。因為我的Author類中并沒有name字段,對應的字段字面量是username。也就是說這裡應該是author.username。但我粗心寫成了author.name(是以為每段代碼編寫unit test是多麼的重要)。更奇葩的是,這條test通過了判斷為真,這裡先不講,後面測試的時候再分析原因。不過這裡一定要改成author.username才是正确的做法。

對應的java接口:

下面開始測試:

先看結果對不對:

test通過了,blog也确實是我們想要的兩條。但仔細觀察結果就會發現幾個問題。第一個問題是author為null,這個我們等下再解決。第二問題是sql查詢語句查詢了author.username like,也就是說我們第二個if節點的test 為true。難道出了問題?我們的Author類明明沒有name字段。是以,這裡要跟蹤下代碼。

好吧,跟蹤了半天一直到ognl内部,還是沒追蹤到為什麼name翻譯成username了。下面還是搞定第一個問題,author為null。

查詢的結果映射到Blog,但blog的author字段并沒有初始化。很容易就猜測到結果集的字段和blog的author不比對。這個就用到resultMap而不是resultType。在上一遍博文中記錄了下來。

Mybatis - 動态sql1.if2.choose
Mybatis - 動态sql1.if2.choose

View Code

這樣測試結果:

Mybatis - 動态sql1.if2.choose
Mybatis - 動态sql1.if2.choose

唯有不斷學習方能改變!

-- <b>Ryan Miao</b>