动态SQL标签产生背景
MyBatis的强大特性之便是它的动态 SQL 。使用过 JDBC或其他类似框架的人都会知道,根据不同条件拼接 SQL 语句时不仅不能忘了必要的空格,还要注意省略掉列名列表最后的逗号,处理方式麻烦且凌乱。
MyBatis 的动态 SQL则能让我们摆脱这种痛苦。MyBatis 之前的版本中,使用动态 SQL 需要学习和了解非常多的标签,现在 MyBatis 采用了功能强大的OGNL ( Object-Graph Navigation Language )表达式语言消除了许多其他标签,以下是 MyBatis的动态 SQL XML 中支持的几种标签
常用动态标签
- • if [^1]
- • choose (when oterwise)
- • trim (where set)
- • foreach
- • bind
- - IF 标签 [^1]
- - WHERE 标签
应用场景:单个或多个条件查询语句
<select id="selectWhere" resultType="auth">
select * from auth
//自动生成 where,条件为空则不生成
<where>
<if test="aId!=null">
aId=#{aId}
</if>
<if test="role!=null and role!='' ">
and aName=#{role}
</if>
</where>
</select>
通过上面的代码我们注意到此IF不同于JAVA代码中的IF没有else只能进行单个判断。那有没有一个标签可以满足多个判断,同时又能出现非是即否的判断呢?
- - choose 选择
- - when 当,类似IF
- - otherwise 否则
应用场景:拥有多项条件,都不符合需要一个默认条件
<select id="selectWhere" resultType="auth">
select * from auth
where 1=1
<choose>
<when test="id!= null">
and id= #{id}
</when>
<when test="userName!= null and userName!=''">
and user name = #{userName}
</when>
<otherwise>
<!--不满足查询-->
and 1 = 2
</otherwise>
</choose>
</select>
在编写SQL语句,我们有可能需要遇到集合数据,如查询语句的 IN( ) 插入语句的 values(param 1),(param 2) 亦或是批量更新 set key=“mm”
- - foreach 循环
适用场景
#查询
<select id="selectInfo" resultType="auth">
select * from user
where id in
//效果 (a,b,c)
<foreach collection="alist" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
#添加
<insert id="insertInfo">
insert into user
values
//效果 (a,b)
<foreach collection="alist" item="user" separator=",">
( #{id} , #{username} )
</foreach>
</insert >
#修改
<update id="modifyInfo">
update user
set
//效果 key=val index对应的是Map中的key
<foreach collection="mapList" item="val" index="key" separator=",">
#{key}=#{val}
</foreach>
</update>
扩展标展:
- - bind 绑定(类似声明赋值)
- - trim where和set标签实现底层
bind 正如一个声明变量并赋值的过程 var one=1;
- bind
场景说明
bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中
<if test=” userNarne != null and userNarne ! = "">
and username like concat (" '%' , #{ userNarne },'%' ")
</if>
使用 concat 函数连接字符串,在 Mysql中,这个函数支持多个参数,但在 Oracle 中只支持两个参数。由于不同数据库之间的语法差异 ,如果更换数据库,有些 SQL 语句可能就需要重写。针对这种情况,可以使用 bind 标签来避免由于更换数据库带来的一些麻烦。将上面的方法改为 bind 方式后,代码如下。
<if test=" userNarne != null and userNarne!=''">
<bind narne="userNarneLike" value="'%'+ userNarne +'%'"
and username like #{userNarneLike}
</if>
- - trim
<where>
标签和<set>
标签在使用时都可根据条件或设置的有无自动判断是否添加
where 标签对应 trim 的实现如下。
//AND和OR后面的空格不能省略,为了避免匹配到andes等单词
prefixOverides 如果where后直接跟AND OR则去掉
<trim prefix="WHERE" prefixOverrides="AND 丨OR " >
</trim>
set 标签对应 trim 实现如下
//suffixOverrides 用法和prefixOverides一致,去掉首字符
<trim prefix="SET" suffixOverrides="," >
</ trim>