Mybatis中的ognl表達式。及myabtis where標簽/if test標簽/trim標簽


1.mybatis默認支持使用ognl表達式來生成動態sql語句

MyBatis中可以使用OGNL的地方有兩處:

  • 動態SQL表達式中
  • ${param}參數中

上面這兩處地方在MyBatis中處理的時候都是使用OGNL處理的。

 

2.Mybatis <where>標簽

復制代碼
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
復制代碼

如果這些條件沒有一個能匹配上將會怎樣?最終這條 SQL 會變成這樣:

SELECT * FROM BLOG
WHERE

這會導致查詢失敗。如果僅僅第二個條件匹配又會怎樣?這條 SQL 最終會是這樣:

SELECT * FROM BLOG
WHERE 
AND title like ‘yiibai.com’

這個查詢也會失敗。這個問題不能簡單的用條件句式來解決,如果你也曾經被迫這樣寫過,那么你很可能從此以后都不想再這樣去寫了。

MyBatis 有一個簡單的處理,這在90%的情況下都會有用。而在不能使用的地方,你可以自定義處理方式來令其正常工作。一處簡單的修改就能得到想要的效果:

復制代碼
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
復制代碼

where 元素知道只有在一個以上的if條件有值的情況下才去插入“WHERE”子句。而且,若最后的內容是“AND”或“OR”開頭的,where 元素也知道如何將他們去除。

如果 where 元素沒有按正常套路出牌,我們還是可以通過自定義 trim 元素來定制我們想要的功能。比如,和 where 元素等價的自定義 trim 元素為:

<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>

 

今天遇到一個場景需要寫一個這樣的查詢語句:

用戶對象userInfo包含下面幾個字段: 
userName phone email qqId weiboId wxId

現在新注冊用戶,傳過來一個注冊userInfo對象,現在要到數據庫中驗證狀態status=1 (表示激活的用戶)的用戶中,是否存在一個用戶,只要它這些字段中至少有一個與新注冊的對象對應的字段內容相同,那就說明重復注冊。

翻譯成sql語句表示一下的意思大概就是: 
select * from tablename where 

userName=”xxx” 
or phone =”xxx” 
or … 

and status=1

一開始我是這樣寫的,在mybatis中的代碼就是這樣:

<select id="selectBySelective" resultType="xxx.UserInfo"> select <include refid="Base_Column_List" /> from uc_user <where> (<if test="userName != null" > user_name = #{userName} </if> <if test="email != null" > or email = #{email} </if> <if test="phone != null" > or phone = #{phone} </if> <if test="weiboId != null" > or weibo_id = #{weiboId} </if> <if test="wxId != null" > or wx_id = #{wxId} </if> <if test="qqId != null" > or qq_id = #{qqId} </if>) </where> and status = 1 </select> 

這樣代碼看似沒有什么問題但是其實是有問題的。為什么呢? 
如果userName 為空,后面某字段不為空,最后的sql語言會成為這樣:

select * from uc_user where(or email = "xxx") and status = 1

使用mybatis < where > 標簽就是為了防止這種情況,mybatis會在第一個 
userName 為空的情況下,幫我們去掉后面的語句的第一個”or”

但是我加了where標簽中加入()后,語句會報錯。因為自動去掉”or”會失效。

查看了mybatis官方文檔發現了另一個標簽 < trim >可以通過自定義 trim 元素來定制我們想要的功能

trim標簽包圍的內容可以設置幾個屬性: 
prefix :內容之前加的前綴 
suffix :內容之后加的后綴 
prefixOverrides: 屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的,多個忽略序列用“|”隔開)。它帶來的結果就是所有在 prefixOverrides 屬性中指定的內容將被移除。

所以我修改后的代碼是:

 <select id="selectBySelective" resultType="xxx.UserInfo"> select <include refid="Base_Column_List" /> from uc_user <trim prefix="WHERE (" suffix=")" prefixOverrides="AND |OR "> <if test="userName != null" > user_name = #{userName} </if> <if test="email != null" > or email = #{email} </if> <if test="phone != null" > or phone = #{phone} </if> <if test="weiboId != null" > or weibo_id = #{weiboId} </if> <if test="wxId != null" > or wx_id = #{wxId} </if> <if test="qqId != null" > or qq_id = #{qqId} </if> </trim> and status = 1 </select>

ok搞定。

 

  1. <select id="getStudentList_if" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity">  
  2.     SELECT ST.STUDENT_ID,  
  3.            ST.STUDENT_NAME,  
  4.            ST.STUDENT_SEX,  
  5.            ST.STUDENT_BIRTHDAY,  
  6.            ST.STUDENT_PHOTO,  
  7.            ST.CLASS_ID,  
  8.            ST.PLACE_ID  
  9.       FROM STUDENT_TBL ST   
  10.      WHERE  
  11.     <if test="studentName !=null ">  
  12.         ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%')  
  13.     </if>  
  14.     <if test="studentSex != null and studentSex != '' ">  
  15.         AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER}  
  16.     </if>  
  17.     <if test="studentBirthday != null ">  
  18.         AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE}  
  19.     </if>  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM