關(guān)于mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接問題
前言
最近在開發(fā)項目的時候涉及到復(fù)雜的動態(tài)條件查詢,但是mybaits
本身不支持if elseif
類似的判斷但是我們可以間接通過 chose when otherwise
去實現(xiàn)其中choose
為一個整體 when
是if otherwise
是else
快速使用
以前我們進(jìn)行條件判斷時候使用if
標(biāo)簽進(jìn)行判斷,條件并列存在
<if test="seat_no != null and seat_no != '' "> AND seat_no = #{seat_no} </if>
現(xiàn)在 使用chose when otherwise
條件只要有一個成立,其他的就不會再判斷了。如果沒有成立的條件則默認(rèn)執(zhí)行otherwise
中的內(nèi)容
<choose> <when test="……"> …… </when> <otherwise> …… </otherwise> </choose>
以下是我自己真實使用的例子,并且經(jīng)過了測試,僅供參考:
根據(jù)動態(tài)條件篩選查詢用戶信息
<select id="findUsersByUser" resultType="cn.soboys.kmall.sys.entity.User"> select tu.USER_ID,tu.USERNAME,tu.SSEX,td.DEPT_NAME,tu.MOBILE,tu.EMAIL,tu.STATUS,tu.CREATE_TIME, td.DEPT_ID from t_user tu left join t_dept td on tu.DEPT_ID = td.DEPT_ID <where> <choose> <when test="userParams.adminType==4"> and tu.ADMIN_TYPE_ID in(2,3) </when> <otherwise> <include refid="search"></include> </otherwise> </choose> </where> </select> <sql id="search"> <if test="userParams.adminType==null or userParams.adminType==''"> and tu.ADMIN_TYPE_ID in(0,1) </if> <if test="userParams.adminType != null and userParams.adminType != ''"> and tu.ADMIN_TYPE_ID=#{userParams.adminType} </if> <if test="userParams.roleId != null and userParams.roleId != ''"> and (select group_concat(ur.ROLE_ID) from t_user u right join t_user_role ur on ur.USER_ID = u.USER_ID, t_role r where r.ROLE_ID = ur.ROLE_ID and u.USER_ID = tu.USER_ID and r.ROLE_ID=#{userParams.roleId}) </if> <if test="userParams.mobile != null and userParams.mobile != ''"> AND tu.MOBILE =#{userParams.mobile} </if> <if test="userParams.username != null and userParams.username != ''"> AND tu.USERNAME like CONCAT('%',#{userParams.username},'%') </if> <if test="userParams.ssex != null and userParams.ssex != ''"> AND tu.SSEX =#{userParams.ssex} </if> <if test="userParams.status != null and userParams.status != ''"> AND tu.STATUS =#{userParams.status} </if> <if test="userParams.deptId != null and userParams.deptId != ''"> AND td.DEPT_ID =#{userParams.deptId} </if> <if test="userParams.createTime != null and userParams.createTime != ''"> AND DATE_FORMAT(tu.CREATE_TIME,'%Y%m%d') BETWEEN substring_index(#{userParams.createTime},'#',1) and substring_index(#{userParams.createTime},'#',-1) </if> </sql>
這里就用到啦 if else if
判斷。 choose
標(biāo)簽中when
條件一但不成立,就會執(zhí)行otherwise
標(biāo)簽中的條件,判斷語句,也就是我下面包含的sql片段條件
更詳細(xì)的條件標(biāo)簽使用參考我這一篇文章點擊進(jìn)入
SQL片段拼接
我們再寫sql語句的時候往往會有這樣一些要求,一些重復(fù)的sql語句片段,我們不想重復(fù)去寫,那么可以通過sql片段方式去抽離,公共sql然后在需要的地方去引用
MyBatis
中 <sql>
元素用于定義一個 SQL
片段,用于分離一些公共的 SQL 語句,例如:SELECT
關(guān)鍵字和 WHERE
關(guān)鍵字之間的部分。其中:
id
:唯一標(biāo)識符,用于在其他地方使用 <include>
標(biāo)簽引用;
lang:
設(shè)置字符編碼;
databaseId
:指定執(zhí)行該 SQL 語句的數(shù)據(jù)庫ID,數(shù)據(jù)庫ID在 mybatis-cfg.xml 中的
同時,你也能夠看見 <sql>
標(biāo)簽中可以使用<include>、<trim>、<where>、<set>、<foreach>、<choose>、<if>、<bind>
等標(biāo)簽定義復(fù)雜的 SQL 片段
簡單使用定義sql片段如下:
<sql id="user_columns"> `user_id`, `name`, `sex`, `age` </sql>
在 <sql>
標(biāo)簽中使用 <include>
標(biāo)簽引入定義的sql片段,如下:
<!-- 定義基礎(chǔ)列 --> <sql id="user_base_columns"> `user_id`, `name` </sql> <!-- 定義一個SQL片段 --> <sql id="user_columns"> <include refid="user_base_columns"/>, `sex`, `age` </sql>
場景使用案例如:查詢用戶信息
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hxstrive.mybatis.sql.demo1.UserMapper"> <!-- 映射結(jié)果 --> <resultMap id="RESULT_MAP" type="com.hxstrive.mybatis.sql.demo1.UserBean"> <id column="user_id" jdbcType="INTEGER" property="userId" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="sex" jdbcType="VARCHAR" property="sex" /> <result column="age" jdbcType="INTEGER" property="age" /> </resultMap> <!-- 定義一個SQL片段 --> <sql id="user_columns"> `user_id`, `name`, `sex`, `age` </sql> <!-- 查詢所有用戶信息 --> <select id="findAll" resultMap="RESULT_MAP"> select <include refid="user_columns" /> from `user` </select> </mapper>
SQL參數(shù)取值和OGNL表達(dá)式
看到我們上面去值參數(shù)通過#{params}
這種方式來去值的其中傳進(jìn)來的參數(shù) #{xx} 就是使用的 OGNL
表達(dá)式。
Mybatis 官方文檔中「XML 映射文件」模塊里邊,有解析到:
說當(dāng)我們使用 #{} 類型參數(shù)符號的時候,其實就是告訴 Mybatis 創(chuàng)建一個預(yù)處理語句參數(shù),通過 JDBC,這樣的一個參數(shù)在 SQL 中會由一個 "?" 來標(biāo)識,并傳遞到一個新的預(yù)處理語句中。
也就是說當(dāng)我們使用 #{XX} OGNL 表達(dá)式的時候, 它會先幫我們生成一條帶占位符的 SQL 語句,然后在底層幫我們設(shè)置這個參數(shù):ps.setInt(1, id);
OGNL 是 Object-Graph Navigation Language 的縮寫,對象-圖行導(dǎo)航語言,語法為:#{ }。
是不是有點懵,不知道這是個啥?
OGNL 作用是在對象和視圖之間做數(shù)據(jù)的交互,可以存取對象的屬性和調(diào)用對象的方法,通過表達(dá)式可以迭代出整個對象的結(jié)構(gòu)圖
MyBatis常用OGNL表達(dá)式如下:
上述內(nèi)容只是合適在MyBatis中使用的OGNL表達(dá)式,完整的表達(dá)式點擊這里。
MyBatis中可以使用OGNL的地方有兩處:
- 動態(tài)
SQL
表達(dá)式中 ${param}
參數(shù)中
如下例子MySql like 查詢:
<select id="xxx" ...> select id,name,... from country <where> <if test="name != null and name != ''"> name like concat('%', #{name}, '%') </if> </where> </select>
上面代碼中test的值會使用OGNL計算結(jié)果。
例二,通用 like 查詢:
<select id="xxx" ...> select id,name,... from country <bind name="nameLike" value="'%' + name + '%'"/> <where> <if test="name != null and name != ''"> name like #{nameLike} </if> </where> </select>
這里
注:對<bind參數(shù)的調(diào)用可以通過#{}或 ${} 方式獲取,#{}可以防止注入。
在通用Mapper中支持一種UUID的主鍵,在通用Mapper中的實現(xiàn)就是使用了
<bind name="username_bind" value='@java.util.UUID@randomUUID().toString().replace("-", "")' />
這種方式雖然能自動調(diào)用靜態(tài)方法,但是沒法回寫對應(yīng)的屬性值,因此使用時需要注意。
${params}
中的參數(shù)
上面like的例子中使用下面這種方式最簡單
<select id="xxx" ...> select id,name,... from country <where> <if test="name != null and name != ''"> name like '${'%' + name + '%'}' </if> </where> </select>
這里注意寫的是${'%' + name + '%'},
而不是%${name}%,
這兩種方式的結(jié)果一樣,但是處理過程不一樣。
在MyBatis
中處理${}
的時候,只是使用OGNL
計算這個結(jié)果值,然后替換SQL中對應(yīng)的${xxx}
,OGNL處理的只是${這里的表達(dá)式}。
這里表達(dá)式可以是OGNL支持的所有表達(dá)式,可以寫的很復(fù)雜,可以調(diào)用靜態(tài)方法返回值,也可以調(diào)用靜態(tài)的屬性值。
例子,條件判斷入?yún)傩灾凳欠癜幼址梢灾苯邮褂?contains
判斷
<foreach collection="list" item="item" index="index" separator="AND" open="(" close=")"> <choose> <when test='item.cname.contains("select") or item.cname.contains("checkbox") or item.cname.contains("date")'> <if test='item.cname.contains("select") or item.cname.contains("checkbox")'> find_in_set(#{item.value},base.${item.cname}) </if> <if test='item.cname.contains("date")'> DATE_FORMAT(base.${item.cname},'%Y-%m-%d') = DATE_FORMAT(#{item.value},'%Y-%m-%d') </if> </when> <otherwise> base.${item.cname} = #{item.value} </otherwise> </choose> </foreach>
到此這篇關(guān)于mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接的文章就介紹到這了,更多相關(guān)mybatis if else if 條件判斷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Event?Sourcing事件溯源模式優(yōu)化業(yè)務(wù)系統(tǒng)
這篇文章主要為大家介紹了Event?Sourcing事件溯源模式優(yōu)化業(yè)務(wù)系統(tǒng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07java自定義注解實現(xiàn)前后臺參數(shù)校驗的實例
下面小編就為大家?guī)硪黄猨ava自定義注解實現(xiàn)前后臺參數(shù)校驗的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11SpringBoot整合Scala構(gòu)建Web服務(wù)的方法
這篇文章主要介紹了SpringBoot整合Scala構(gòu)建Web服務(wù)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03jxls2.4.5如何動態(tài)導(dǎo)出excel表頭與數(shù)據(jù)
這篇文章主要介紹了jxls2.4.5如何動態(tài)導(dǎo)出excel表頭與數(shù)據(jù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08