Mybatis如何使用ognl表達(dá)式實(shí)現(xiàn)動(dòng)態(tài)sql
新建Users實(shí)體類:
public class Users { private Integer uid; private String userName; private String tel; //添加上面私有字段的get、set方法}
新建一個(gè)Dao接口類,mybatis配置文件在配置namespace屬性時(shí)需要加入這個(gè)類的完整類名,找到這個(gè)類里的方法執(zhí)行:
public interface UserDao { /** * 依據(jù)userName查詢用戶信息 * @param user * @return */ List<Users> listUser(Users user); /** * 動(dòng)態(tài)選擇條件 * @param user * @return */ List<Users> listUser2(Users user); /** * 動(dòng)態(tài)范圍查詢 * @param uids * @return */ List<Users> listUser3(Integer[] uids); /** * 動(dòng)態(tài)更新用戶信息 * @param user */ void updateUser(Users user); /** * 批量添加 * @param list */ void addBatch(List<Users> list); /** * 批量刪除 * @param ids */ void deleteBatch(int[] ids); /** * 批量更新 * @param list */ void updateBatch1(List<Users> list); /** * 批量更新 * @param list */ void updateBatch2(List<Users> list);}
新建mybatis的配置文件(下面代碼可以作為mybatis配置文件的模板,這里的namespace屬性可以設(shè)置為上面的dao類的完整類名):
<?xml version='1.0' encoding='utf-8'?><!DOCTYPE mapper PUBLIC '-//mybatis.org//DTD Mapper 3.0//EN''http://mybatis.org/dtd/mybatis-3-mapper.dtd'><!-- mapper根節(jié)點(diǎn)的namespace指定Dao接口的完整類名,因?yàn)閙ybatis在解析的時(shí)候要根據(jù)這個(gè)類名找到相應(yīng)dao方法執(zhí)行 --><mapper namespace=''> </mapper>
在mybatis配置文件中寫一條條件查詢sql語(yǔ)句:
<!-- 動(dòng)態(tài)查詢(使用if拼接條件,適用于多選多的形式) --><select parameterType='users' resultMap='userMap'> select u_id, u_name, u_tel from user_info4 user_info <where><if test='userName != null and userName !=’’'> u_name = #{userName}</if><if test='tel != null and tel !=’’'> and u_tel = #{tel}</if> </where></select>
這里使用了where和if標(biāo)簽,<where></where>意思就是sql語(yǔ)句中的where,當(dāng)然,where直接在sql中寫出來也可以,<if></if>標(biāo)簽就是條件判斷,test屬性中寫條件語(yǔ)句,如果test中的條件語(yǔ)句為true,那么標(biāo)簽中的sql語(yǔ)句就會(huì)拼接到上面的sql語(yǔ)句中,所以這條sql語(yǔ)句的意思就是如果傳過來的Users對(duì)象中,userName字段不為null,或字段值不為空,那么就添加一個(gè)對(duì)userName的查詢,tel也是如此。
注意:在對(duì)tel字段的判斷時(shí),標(biāo)簽中的sql語(yǔ)句前加了一個(gè)and,如果前一條判斷為false,那么mybatis會(huì)自動(dòng)將and關(guān)鍵字刪除。
<!-- 動(dòng)態(tài)查詢(使用choose選擇條件,適用于多選一) --><select parameterType='users' resultMap='userMap'> select u_id, u_name, u_tel from user_info4 <choose><when test='userName != null and userName != ’’'> where u_name = #{userName}</when><when test='tel != null and tel != ’’'> where u_tel = #{tel}</when><otherwise> order by u_id desc</otherwise> </choose></select>
這里使用的是choose-when-otherwise標(biāo)簽,有點(diǎn)類似于java中的switch-case-default選擇條件語(yǔ)句,相比于if標(biāo)簽,這里只能選擇一個(gè),即多選一。
在這條sql語(yǔ)句中,會(huì)按順序判斷when子句,如果所有的when子句都為false,則會(huì)執(zhí)行otherwise子句中的sql語(yǔ)句。
<!-- 動(dòng)態(tài)查詢(使用foreach范圍查詢,適用于in和or語(yǔ)句) --><!-- int[] ids = new int[]{1,2,3,4}; --><select parameterType='collection' resultMap='userMap'> select u_id, u_name, u_tel from user_info4 <where>u_id in<if test='array != null'> <foreach collection='array' item='id' open='(' separator=',' close=')'>#{id} </foreach></if> </where></select>
foreach標(biāo)簽適用于范圍查詢(in和or語(yǔ)句),如遍歷一個(gè)id集合,查詢出集合中所有id對(duì)應(yīng)的用戶。在foreach標(biāo)簽中,collection屬性指定需要遍歷的集合的名稱,這里只有一個(gè)參數(shù),所以可以隨意取;item指定遍歷的每一項(xiàng)的別名,open指定在遍歷前需要加上的內(nèi)容,separator指定每遍歷一個(gè)后加上的內(nèi)容,close指定遍歷完后需要加上的內(nèi)容,如遍歷上面的ids集合,那么最終得到的內(nèi)容就是 (1,2,3,4) 。
<!-- 動(dòng)態(tài)更新(使用set動(dòng)態(tài)更新字段) --><update parameterType='users' > update user_info4 <trim prefix='set' suffixOverrides=','><if test='userName != null and userName != ’’'> u_name = #{userName},</if><if test='tel != null and tel != ’’'> u_tel = #{tel}</if> </trim> <!-- where u_id = #{uid} --> <where>u_id = #{uid} </where></update>
trim標(biāo)簽用于動(dòng)態(tài)設(shè)值,例如在更新數(shù)據(jù)時(shí),可以動(dòng)態(tài)將改變的字段設(shè)置。在trim標(biāo)簽中,prefix屬性表示在更新字段之前添加set關(guān)鍵字,suffixOverrides表示將最后一個(gè)更新字段的逗號(hào)替換成suffix指定的空格符,如果不指定suffix默認(rèn)就是空格。
<!-- 批量添加,利用sql的特性 --><insert parameterType='list'> insert into user_info4(u_id, u_name, u_tel) values <foreach collection='list' item='user' separator=','>(#{user.uid}, #{user.userName}, #{user.tel}) </foreach></insert>
foreach標(biāo)簽不僅可以用于范圍查詢,還可以遍歷集合用于批量添加。
因?yàn)榭梢岳胹ql的特性,例如:insert into user_info4(u_name, u_tel) values(’’, ’’), (’’, ’’), (’’, ’’);這樣執(zhí)行這條sql語(yǔ)句就可以實(shí)現(xiàn)批量添加。
<!-- 批量更新1,這一種方式兼容性較好,當(dāng)數(shù)據(jù)量大時(shí) --><update parameterType='list'> <foreach collection='list' item='user' separator=';'>update user_info4<set> u_name = #{user.userName}</set>where u_id = #{user.uid} </foreach></update>
foreach還可以用于遍歷出多條sql語(yǔ)句,使得一次可以執(zhí)行多條sql,當(dāng)然,如果需要MySql執(zhí)行多條批量操作時(shí),需要開啟批量查詢功能,即在MySql的url中加入 allowMultiQueries=true 。
<!-- 批量更新2,使用MySQL的case when語(yǔ)句 --> <update parameterType='list'>update user_info4 set u_name = case u_id<foreach collection='list' item='user' separator=' '> when #{user.uid} then #{user.userName}</foreach>endwhere u_id in<foreach collection='list' item='user' open='(' close=')' separator=','> #{user.uid}</foreach> </update>
這里使用的是MySql中的case when語(yǔ)句來更新的,基本語(yǔ)法:
update user_info4 set u_name = case u_idwhen 3 then ’游客1’when 4 then ’游客2’endwhere u_id in(3,4);Mybatis中的ognl使用總結(jié)
經(jīng)常在寫mapper中用到一些OGNL,但是沒怎么總結(jié),使用方法一直模模糊糊的。抽點(diǎn)時(shí)間,查了別人的blog,做個(gè)簡(jiǎn)單的總結(jié)
1.概念OGNL,Object Graph Navigation Language,是一種強(qiáng)大的表達(dá)式語(yǔ)言,網(wǎng)上搜索這個(gè)概念,多是和structs有關(guān)的。但是在mybatis中OGNL應(yīng)用很廣的;
2.基本參數(shù)Mybatis中常用的OGNL表達(dá)式有以下:
e1 or e2
e1 and e2
e1 == e2,e1 eq e2
e1 != e2,e1 neq e2
e1 lt e2:小于
e1 lte e2:小于等于,其他gt(大于),gte(大于等于)
e1 in e2
e1 not in e2
e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2
!e,not e:非,求反
e.method(args)調(diào)用對(duì)象方法
e.property對(duì)象屬性值
e1[ e2 ]按索引取值,List,數(shù)組和Map
@class@method(args)調(diào)用類的靜態(tài)方法
@class@field調(diào)用類的靜態(tài)字段值
更加詳細(xì)的介紹可以參考官網(wǎng)的介紹:https://commons.apache.org/proper/commons-ognl/language-guide.html
在一定意義上說,mybatis中的動(dòng)態(tài)sql也是基于OGNL表達(dá)式的。其中常用的元素有如下幾種:
if choose(when,otherwise) trim where set foreach3.應(yīng)用;
OGNL在mybatis中的應(yīng)用,主要有兩種;
1)動(dòng)態(tài)SQL表達(dá)式;
舉個(gè)栗子:
<code class='language-xml hljs has-numbering'><span class='hljs-tag'><<span class='hljs-title'>select</span> <span class='hljs-attribute'>id</span>=<span class='hljs-value'>'demo1'</span> <span class='hljs-attribute'>...</span>></span></code><pre name='code' class='prettyprint'><code class='language-xml hljs has-numbering'> select id, name from users <span class='hljs-tag'><<span class='hljs-title'>bind</span> <span class='hljs-attribute'>name</span>=<span class='hljs-value'>'nameLike'</span> <span class='hljs-attribute'>value</span>=<span class='hljs-value'>'’%’ + name + ’%’'</span>/></span> <span class='hljs-tag'><<span class='hljs-title'>where</span>></span><span class='hljs-tag'><<span class='hljs-title'>if</span> <span class='hljs-attribute'>test</span>=<span class='hljs-value'>'name != null and name != ’’'</span>></span> name like ’${nameLike}’<span class='hljs-tag'></<span class='hljs-title'>if</span>></span> <span class='hljs-tag'></<span class='hljs-title'>where</span>></span><span class='hljs-tag'></<span class='hljs-title'>select</span>></span></code>
其中的bind中的value值會(huì)使用OGNL計(jì)算,ps,其中bind的參數(shù)調(diào)用只能用$獲取;
2)${param}參數(shù)中
<code class='language-xml hljs has-numbering'><span class='hljs-tag'><<span class='hljs-title'>select</span> <span class='hljs-attribute'>id</span>=<span class='hljs-value'>'demo2'</span> <span class='hljs-attribute'>...</span>></span> select id,name from users <span class='hljs-tag'><<span class='hljs-title'>where</span>></span><span class='hljs-tag'><<span class='hljs-title'>if</span> <span class='hljs-attribute'>test</span>=<span class='hljs-value'>'name != null and name != ’’'</span>></span> name like ’${’%’ + name + ’%’}’<span class='hljs-tag'></<span class='hljs-title'>if</span>></span> <span class='hljs-tag'></<span class='hljs-title'>where</span>></span><span class='hljs-tag'></<span class='hljs-title'>select</span>></span></code>
此處寫的是 ${’%’ + name + ’%’},而不是 %${name}%,這兩種方式的結(jié)果一樣,但是處理過程不一樣。
ps,說明一下#和$的區(qū)別:${} 為原樣輸出,你傳什么,sql里就填入什么,比如有引號(hào)它也會(huì)原樣填到sql里。#{} 會(huì)使用 PreparedStatement,變量處用 ? 代替。
在能使用 #{} 盡量使用它吧,可以防止sql注入。
以下是一個(gè)OGNL的調(diào)用靜態(tài)方法的示例:
<select parameterType='java.lang.String' resultType='java.lang.String'> select title from song_question where questionState = #{value} <if test='@Ognl@isSolve(value[0],0)'> order by questionTime desc </if> <if test='@Ognl@isSolve(value[0],1)'> order by answerTime desc </if> limit 0,1</select>
靜態(tài)方法如下:
public static boolean isSolve(Object o,String soleState){ if(o == null) return false; String str = null; if(o instanceof String[]){ String[]objects = (String[])o; str = objects[0]; }else if(o instanceof Character){ Character c = (Character) o; str = Character.toString(c); } if(StringUtils.equals(str, soleState)) return true; return false;}
如果值為0,則order by questionTime desc 根據(jù)字段questionTime排序。
如果值為1,則order by answerTime desc根據(jù)字段answerTime排序。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. DB2 V9.5工作負(fù)載管理之工作負(fù)載管理簡(jiǎn)介2. SQL Server數(shù)據(jù)庫(kù)的三種創(chuàng)建方法匯總3. ubuntu下使用SQLite3的基本命令4. MySQL存儲(chǔ)過程in、out和inout參數(shù)示例和總結(jié)5. SQL SERVER – 檢測(cè)LOCK、終止會(huì)話 ID/UOW 的用戶進(jìn)程6. 使用DB2look 重新創(chuàng)建優(yōu)化器訪問計(jì)劃(3)(1)7. 國(guó)內(nèi)學(xué)院派專家對(duì)DB2 9新產(chǎn)品贊不絕口8. SQLite教程(四):內(nèi)置函數(shù)9. DB2 自動(dòng)遞增字段實(shí)現(xiàn)方法10. 目前學(xué)習(xí)到的常用命令之Mariadb
