動態SQL概況
MyBatis 的強大特性之一便是它的動態 SQL
在Java開發中經常遇到條件判斷,比如:
if(x>0){
//執行一些邏輯........
}
Mybatis應用中,SQL映射通常位於XML文件內,在執行前需要將XML中的映射轉換為最終要執行的SQL
在轉換中是否可以根據輸入動態的處理SQL?這就是動態SQL,比如
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
上面的<if test="title != null"> 就是動態SQL處理,將會根據實際傳遞的title的值,動態的決定SQL的內容,是否包含最后面的AND
Mybatis的動態SQL元素不多,但是簡單高效,Mybatis的動態SQL元素類似JSTL
類型主要有三種:
- 條件判斷
- 內容處理
- 循環處理
對於每種不同的類型又有各自的格式和屬性
條件處理
if是最基本的一種形式,語意為:如果xxx就xxx
通過最基本的if可以構造很復雜的條件測試語句,相當於
if(){ }
choose是特殊化的if,相當於
if(){ }else{ }
你可以添加多個if,比如
if(){ }if(){ }if(){ }else{ }
通常對於一個choose是可以拆分為多個if條件的,但是很顯然,某些場景下,使用if else的形式比多個if 要更加簡單清晰
if和choose里面when后的條件都是使用test進行設置的
內容處理
trim用於動態內容頭尾的處理,可以添加前綴prefix或者添加后綴suffix
也可以移除匹配的指定的前綴prefixOverrides,或者移除匹配的指定的后綴suffixOverrides
簡言之可以借助於trim對拼接內容的頭尾進行處理
where相當於
<trim prefix="WHERE" prefixOverrides="AND |OR ">
set相當於<trim prefix="SET" suffixOverrides=",">
循環遍歷
foreach用於動態的循環拼接,相當於for循環動態拼接內容
for(int i =0;i<list.size;i++){ String s +=“...”; }
對於foreach,需要指明需要遍歷循環的參數名稱,通過collection指定
需要指定循環變量,也就是在循環中使用哪個變量指代,相當於Object o = list.get(i); 使用item指定的就是這個o
還可以指定變量用於記錄索引,通過這個索引變量可以獲得迭代的次數索引,通過index
對於open, separator, close,就是在字符串拼接的開頭,中間,結尾,添加的分割符信息。
總結
在實際項目應用中,總是有很多的查詢條件或者關聯語句,但是並不是每一次的查詢都需要完整的語句,難道每種場景都重新寫一個SQL嗎?
顯然是效率低下的,Mybatis的動態SQL就是解決這種問題的
動態SQL就是根據條件動態的處理SQL語句,進而達到不同場景不同SQL的作用,也就是寫一次SQL,然后經過條件分支或者內容的處理,能夠在多個場景進行使用
從上面的介紹也可以看得出來,動態SQL的本質在於根據條件,對SQL語句處理,可以理解為文本處理工作
他只是Mybatis一次執行時實際執行的SQL語句,不管是if還是choose 還是where還是trim,再或者是foreach,都是簡單的對SQL進行拼接、處理、優化
對於程序員來說,最重要的就是條件的判斷,也就是test后面的語句的書寫,再就是確認各種條件判斷后處理后的SQL語句不會出現什么問題就夠了
但是還需要注意,盡管Mybatis有動態SQL功能,可以靈活的拼接SQL,但是也不要濫用,盡可能業務邏輯比較相似的,通過條件進行控制
試想,如果一整個表的所有邏輯全都是一個SQL,通過各種if choose拼接起來,可讀性是一個很大的問題,所以也要合理
簡單說幾點就是:
- 動態SQL本質就是SQL語句的文本處理工作,無他
- 要注意條件語句的設置
- 不要濫用動態SQL,該分開還是得分開
對於動態SQL根本仍舊是SQL的編寫,所以需要具有良好的SQL語句編寫能力,動態SQL只是可以讓他更加靈活,並不能解決你SQL中的任何問題,或者性能問題
要始終記住,他只是處理需要執行的SQL