Myibatis 動態SQL

[code="java"]動態 SQL
MyBatis 的一個強大的特性之一通常是它的動態 SQL 能力。 如果你有使用 JDBC 或其他 相似框架的經驗,你就明白條件地串聯 SQL 字符串在一起是多麼的痛苦,確保不能忘了空 格或在列表的最後省略逗號。動態 SQL 可以徹底處理這種痛苦。
通常使用動態 SQL 不可能是獨立的一部分,MyBatis 當然使用一種強大的動態 SQL 語 言來改進這種情形,這種語言可以被用在任意映射的 SQL 語句中。
動態 SQL 元素和使用 JSTL 或其他相似的基於 XML 的文本處理器相似。在 MyBatis 之 前的版本中,有很多的元素需要來了解。MyBatis 3 大大提升了它們,現在用不到原先一半 的元素就能工作了。MyBatis 採用功能強大的基於 OGNL 的表達式來消除其他元素。
if
choose (when, otherwise)
trim (where, set)
foreach
if
在動態 SQL 中所做的最通用的事情是包含部分 where 字句的條件。比如:

SELECT * FROM BLOG
WHERE state = ‘ACTIVE’

AND title like #{title}


這條語句會提供一個可選的文本查找功能。如果你沒有傳遞 title,那麼所有激活的博客 都會被返回。但是如果你傳遞了 title,那麼就會查找相近的 title(對於敏銳的檢索,這中情 況下你的參數值需要包含任意的遮掩或通配符)的博客。
假若我們想可選地搜索 title 和 author 呢?首先,要改變語句的名稱讓它有意義。然後 簡單加入另外的一個條件。

SELECT * FROM BLOG WHERE state = ‘ACTIVE’

AND title like #{title}


AND author_name like #{author.name}


choose, when, otherwise
有時我們不想應用所有的條件, 相反我們想選擇很多情況下的一種。 Java 中的 switch 和 語句相似,MyBatis 提供 choose 元素。
我們使用上面的示例,但是現在我們來搜索當 title 提供時僅有 title 條件,當 author 提 供時僅有 author 條件。如果二者都沒提供,只返回 featured blogs(也許是由管理員策略地選 擇的結果列表,而不是返回大量沒有意義的隨機博客結果列表)。

SELECT * FROM BLOG WHERE state = ‘ACTIVE’


AND title like #{title}


AND author_name like #{author.name}


AND featured = 1



trim, where, set
前面的例子已經方便地處理了一個臭名昭著的動態 SQL 問題。要考慮我們回到“if”示 例後會發生什麼,但是這次我們將“ACTIVE = 1”也設置成動態的條件。

SELECT * FROM BLOG
WHERE

state = #{state}


AND title like #{title}


AND author_name like #{author.name}


如果這些條件都沒有匹配上將會發生什麼?這條 SQL 結束時就會成這樣:
SELECT * FROM BLOG
WHERE
這會導致查詢失敗。如果僅僅第二個條件匹配是什麼樣的?這條 SQL 結束時就會是這 樣:
SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’
這個查詢也會失敗。這個問題不能簡單的用條件來解決,如果你從來沒有這樣寫過,那 麼你以後也不會這樣來寫。
MyBatis 有一個簡單的處理,這在 90%的情況下都會有用。而在不能使用的地方,你可 以自定義處理方式。加上一個簡單的改變,所有事情都會順利進行:

SELECT * FROM BLOG


state = #{state}


AND title like #{title}


AND author_name like #{author.name}



where 元素知道如果由被包含的標記返回任意內容,就僅僅插入“WHERE” 。而且,如 果以“AND”或“OR”開頭的內容,那麼就會跳過 WHERE 不插入。
如果 where 元素沒有做出你想要的,你可以使用 trim 元素來自定義。比如,和 where 元素相等的 trim 元素是:

...
prefixOverrides 屬性採用管道文本分隔符來覆蓋, 這裏的空白也是重要的。 它的結果就是移除 在 prefixOverrides 屬性中指定的內容,插入在 with 屬性中的內容。
和動態更新語句相似的解決方案是 set。set 元素可以被用於動態包含更新的列,而不包 含不需更新的。比如:

update Author

username=#{username},
password=#{password},
email=#{email},
bio=#{bio}

where id=#{id}
這裏,set 元素會動態前置 SET 關鍵字,而且也會消除任意無關的逗號,那也許在應用 條件之後來跟蹤定義的值。
如果你對和這相等的 trim 元素好奇,它看起來就是這樣的:

...
注意這種情況下我們覆蓋一個後綴,而同時也附加前綴。
foreach
另外一個動態 SQL 通用的必要操作是迭代一個集合, 通常是構建在 IN 條件中的。 比如:

SELECT *
FROM POST P
WHERE ID in

#{item}


foreach 元素是非常強大的,它允許你指定一個集合,聲明集合項和索引變量,它們可 以用在元素體內。它也允許你指定開放和關閉的字符串,在迭代之間放置分隔符。這個元素 是很智能的,它不會偶然地附加多餘的分隔符。
注意 你可以傳遞一個 List 實例或者數組作爲參數對象傳給 MyBatis。當你這麼做的時 候,MyBatis 會自動將它包裝在一個 Map 中,用名稱在作爲鍵。List 實例將會以“list” 作爲鍵,而數組實例將會以“array”作爲鍵。
這個部分是對關於 XML 配置文件和 XML 映射文件的而討論的。下一部分將詳細討論 Java API,所以你可以得到你已經創建的最有效的映射。
Multi-db vendor support
If a databaseIdProvider was configured a "_databaseId" variable is available for dynamic code, so you can build different statements depending on database vendor. Have a look at the following example:



select seq_users.nextval from dual


select nextval for seq_users from sysibm.sysdummy1"


insert into users values (#{id}, #{name})
[/code]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章