關(guān)于mybatis if else if 條件判斷SQL片段表達(dá)式取值和拼接問(wèn)題
前言
最近在開(kāi)發(fā)項(xiàng)目的時(shí)候涉及到復(fù)雜的動(dòng)態(tài)條件查詢(xún),但是mybaits本身不支持if elseif類(lèi)似的判斷但是我們可以間接通過(guò) chose when otherwise 去實(shí)現(xiàn)其中choose為一個(gè)整體 when是if otherwise是else
快速使用
以前我們進(jìn)行條件判斷時(shí)候使用if標(biāo)簽進(jìn)行判斷,條件并列存在
<if test="seat_no != null and seat_no != '' ">
AND seat_no = #{seat_no}
</if>
現(xiàn)在 使用chose when otherwise條件只要有一個(gè)成立,其他的就不會(huì)再判斷了。如果沒(méi)有成立的條件則默認(rèn)執(zhí)行otherwise中的內(nèi)容
<choose> <when test="……"> …… </when> <otherwise> …… </otherwise> </choose>
以下是我自己真實(shí)使用的例子,并且經(jīng)過(guò)了測(cè)試,僅供參考:
根據(jù)動(dòng)態(tài)條件篩選查詢(xún)用戶(hù)信息
<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條件一但不成立,就會(huì)執(zhí)行otherwise標(biāo)簽中的條件,判斷語(yǔ)句,也就是我下面包含的sql片段條件
更詳細(xì)的條件標(biāo)簽使用參考我這一篇文章點(diǎn)擊進(jìn)入
SQL片段拼接
我們?cè)賹?xiě)sql語(yǔ)句的時(shí)候往往會(huì)有這樣一些要求,一些重復(fù)的sql語(yǔ)句片段,我們不想重復(fù)去寫(xiě),那么可以通過(guò)sql片段方式去抽離,公共sql然后在需要的地方去引用
MyBatis 中 <sql> 元素用于定義一個(gè) SQL 片段,用于分離一些公共的 SQL 語(yǔ)句,例如:SELECT 關(guān)鍵字和 WHERE 關(guān)鍵字之間的部分。其中:
id:唯一標(biāo)識(shí)符,用于在其他地方使用 <include> 標(biāo)簽引用;
lang:設(shè)置字符編碼;
databaseId:指定執(zhí)行該 SQL 語(yǔ)句的數(shù)據(jù)庫(kù)ID,數(shù)據(jù)庫(kù)ID在 mybatis-cfg.xml 中的
同時(shí),你也能夠看見(jiàn) <sql> 標(biāo)簽中可以使用<include>、<trim>、<where>、<set>、<foreach>、<choose>、<if>、<bind>等標(biāo)簽定義復(fù)雜的 SQL 片段
簡(jiǎn)單使用定義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>
<!-- 定義一個(gè)SQL片段 -->
<sql id="user_columns">
<include refid="user_base_columns"/>, `sex`, `age`
</sql>
場(chǎng)景使用案例如:查詢(xún)用戶(hù)信息
<?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>
<!-- 定義一個(gè)SQL片段 -->
<sql id="user_columns">
`user_id`, `name`, `sex`, `age`
</sql>
<!-- 查詢(xún)所有用戶(hù)信息 -->
<select id="findAll" resultMap="RESULT_MAP">
select <include refid="user_columns" /> from `user`
</select>
</mapper>
SQL參數(shù)取值和OGNL表達(dá)式
看到我們上面去值參數(shù)通過(guò)#{params}這種方式來(lái)去值的其中傳進(jìn)來(lái)的參數(shù) #{xx} 就是使用的 OGNL 表達(dá)式。
Mybatis 官方文檔中「XML 映射文件」模塊里邊,有解析到:
說(shuō)當(dāng)我們使用 #{} 類(lèi)型參數(shù)符號(hào)的時(shí)候,其實(shí)就是告訴 Mybatis 創(chuàng)建一個(gè)預(yù)處理語(yǔ)句參數(shù),通過(guò) JDBC,這樣的一個(gè)參數(shù)在 SQL 中會(huì)由一個(gè) "?" 來(lái)標(biāo)識(shí),并傳遞到一個(gè)新的預(yù)處理語(yǔ)句中。

也就是說(shuō)當(dāng)我們使用 #{XX} OGNL 表達(dá)式的時(shí)候, 它會(huì)先幫我們生成一條帶占位符的 SQL 語(yǔ)句,然后在底層幫我們?cè)O(shè)置這個(gè)參數(shù):ps.setInt(1, id);
OGNL 是 Object-Graph Navigation Language 的縮寫(xiě),對(duì)象-圖行導(dǎo)航語(yǔ)言,語(yǔ)法為:#{ }。
是不是有點(diǎn)懵,不知道這是個(gè)啥?
OGNL 作用是在對(duì)象和視圖之間做數(shù)據(jù)的交互,可以存取對(duì)象的屬性和調(diào)用對(duì)象的方法,通過(guò)表達(dá)式可以迭代出整個(gè)對(duì)象的結(jié)構(gòu)圖
MyBatis常用OGNL表達(dá)式如下:

上述內(nèi)容只是合適在MyBatis中使用的OGNL表達(dá)式,完整的表達(dá)式點(diǎn)擊這里。
MyBatis中可以使用OGNL的地方有兩處:
- 動(dòng)態(tài)
SQL表達(dá)式中 ${param}參數(shù)中
如下例子MySql like 查詢(xún):
<select id="xxx" ...>
select id,name,... from country
<where>
<if test="name != null and name != ''">
name like concat('%', #{name}, '%')
</if>
</where>
</select>
上面代碼中test的值會(huì)使用OGNL計(jì)算結(jié)果。
例二,通用 like 查詢(xún):
<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>
這里
注:對(duì)<bind參數(shù)的調(diào)用可以通過(guò)#{}或 ${} 方式獲取,#{}可以防止注入。
在通用Mapper中支持一種UUID的主鍵,在通用Mapper中的實(shí)現(xiàn)就是使用了
<bind name="username_bind"
value='@java.util.UUID@randomUUID().toString().replace("-", "")' />
這種方式雖然能自動(dòng)調(diào)用靜態(tài)方法,但是沒(méi)法回寫(xiě)對(duì)應(yīng)的屬性值,因此使用時(shí)需要注意。
${params}中的參數(shù)
上面like的例子中使用下面這種方式最簡(jiǎn)單
<select id="xxx" ...>
select id,name,... from country
<where>
<if test="name != null and name != ''">
name like '${'%' + name + '%'}'
</if>
</where>
</select>
這里注意寫(xiě)的是${'%' + name + '%'},而不是%${name}%,這兩種方式的結(jié)果一樣,但是處理過(guò)程不一樣。
在MyBatis中處理${}的時(shí)候,只是使用OGNL計(jì)算這個(gè)結(jié)果值,然后替換SQL中對(duì)應(yīng)的${xxx},OGNL處理的只是${這里的表達(dá)式}。
這里表達(dá)式可以是OGNL支持的所有表達(dá)式,可以寫(xiě)的很復(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)用位運(yùn)算維護(hù)狀態(tài)碼
位運(yùn)算是一種非常高效的運(yùn)算方式,在算法考察中比較常見(jiàn),那么業(yè)務(wù)代碼中我們?nèi)绾问褂梦贿\(yùn)算呢,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧2024-03-03
springboot layui hutool Excel導(dǎo)入的實(shí)現(xiàn)
本文主要介紹了springboot layui hutool Excel導(dǎo)入的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03
java中實(shí)現(xiàn)對(duì)象排序的兩種方法(Comparable,Comparator)
這篇文章主要給大家介紹了關(guān)于java中實(shí)現(xiàn)對(duì)象排序的兩種方法,一種是實(shí)現(xiàn)Comparable進(jìn)行排序,另一種是實(shí)現(xiàn)Comparator進(jìn)行排序,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
java二叉樹(shù)的幾種遍歷遞歸與非遞歸實(shí)現(xiàn)代碼
這篇文章主要介紹了java二叉樹(shù)的幾種遍歷遞歸與非遞歸實(shí)現(xiàn)代碼,需要的朋友可以參考下2020-12-12
Java利用正則取標(biāo)簽之間的數(shù)據(jù)
這篇文章主要介紹了Java利用正則取標(biāo)簽之間的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Java實(shí)現(xiàn)聯(lián)系人管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)聯(lián)系人管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
JAVA正則表達(dá)式校驗(yàn)qq號(hào)碼的方法
Java作為一種開(kāi)發(fā)語(yǔ)言,有許多值得推薦的地方,但是它一直以來(lái)沒(méi)有自帶對(duì)正則表達(dá)式的支持。下面小編給大家?guī)?lái)了JAVA正則表達(dá)式校驗(yàn)qq號(hào)碼的方法,需要的朋友參考下吧2018-04-04
Java 實(shí)用工具類(lèi)Spring 的 AnnotationUtils詳解
Spring 框架提供了一個(gè)強(qiáng)大的注解工具類(lèi) org.springframework.core.annotation.AnnotationUtils,用于簡(jiǎn)化注解的獲取、合成與解析過(guò)程,本文給大家介紹Java 實(shí)用工具類(lèi):Spring 的 AnnotationUtils,感興趣的朋友一起看看吧2025-04-04
簡(jiǎn)單總結(jié)Java IO中stream流的使用方法
這篇文章主要介紹了Java IO中stream流的使用方法的簡(jiǎn)單總結(jié),包括數(shù)據(jù)流和打印流等Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-03-03

