1, MyBatis动态SQL
- 动态SQL是MyBatis框架中特性之一,在一些组合查询页面需要根据用户输入的条件不同生成不同的查询SQL语句,在JDBC或其他相似框架中需要在代码中拼接SQL语句,容易出错。MyBatis动态SQL可以解决这种问题。
动态SQL标签与JSTL标签相似,它允许在xml中构建不同的SQL语句,常用SQL标签:
- 判断标签: if, choose(when,otherwise)
- 关键字标签: where,set,trim
- 循环标签: foreach
1.1 if 标签
- if标签是简单条件判断逻辑,满足指定条件时追加if标签内的sql语句,不满足时不增加。
<select>
sql语句1
<if test="条件表达式">
sql语句2
</if>
</select>
- if 标签最常见的使用是在where字句部分,根据不同的条件追加不同的SQL语句。
1.2 choose 标签
- choose 标签的作用相当于Java 的 switch 语句,和JSTL中的choose标签作用和用法一致,通常与when和otherwise搭配使用。
<select>
sql语句1
<choose>
<when test="条件表达式">
sql语句2
</when>
<when test="条件表达式">
sql语句3
</when>
<otherwise>
sql语句4
</otherwise>
</choose>
</select>
1.3 where 标签
- where 标签可以在 <where> 标签所在的位置输出一个where关键字,而且可以将后面多余的 and 或者 or 关键字去除。
<select>
select * from emp
<where>
<if test="deptno!=null">
deptno=#{deptno}
</if>
<if test="salary!=null">
and salary=#{salary}
</if>
</where>
</select>
1.4 set 标签
- set 标签主要用在更新操作时,功能和where标签相似,在 <set> 标签所在的位置输出一个set 关键字,可以去除与内容结尾无关的逗号。
<update>
update emp
<set>
<if test="empno!=null">
where empno=#{empno},
</if>
<if test="deptno!=null">
where deptno=#{deptno},
</if>
</set>
<if test="empno!=null">
where empno=#{empno}
</if>
</update>
1.5 trim 标签主要功能:
- 可以在自己包含的内容前面(或者后面)加上某些前缀,与之对应的属性是 prefix 和 suffix。
- 可以把包含内容前或者后的某些内容过滤,即忽略,对应的属性是 prefixOverrides 和 suffixOverrides。
<!-- 等价于where标签 -->
<!-- 忽略语句前的 "and" 和 "or" -->
<trim prefix="where" prefixOverrides="and | or">
...
</trim>
<!-- 等价于set标签 -->
<!-- 忽略语句后的 "," -->
<trim prefix="set" suffixOverrides=",">
...
</trim>
1.6 foreach 标签
- foreach 标签实现循环逻辑,可以进行一个集合迭代,主要用在构建IN条件中。
<!-- select * from emp where empno in (1001.1003.1005); -->
<select>
select * from emp where empno in
<foreach collection="集合" item="迭代变量" open="(" close=")" separator="间隔符(一般是',')">
#{迭代变量}
</foreach>
</select>
<!-- insert into dept values( 1 ,"研发部"),( 2 ,"财务部"),( 3 ,"市场部"); -->
<insert>
insert into dept values
<foreach collection="depts" item="dept" separator=",">
(#{dept.deptno},#{dept.dname})
</foreach>
</insert>
- foreach 标签它允许指定一个集合,声明集合项和索引变量,变量可以用在标签体内,它允许指定开放和关闭的字符串,在迭代项之间放置分隔符。
1.7 bind 标签
- bind 标签可以从OGNL表达式中创建一个变量,并将其绑定到上下文。
mapper.xml 中字符串拼接:
- 使用连接函数
select * from emp where ename like concat('%',#{ename},'%')
- 使用build标签
<select id="findByEname" parameterType="Condition" resultType="Emp">
<bind name="emp_ename" value="'%'+ename+'%'"/>
select * from emp where ename like #{emp_ename}
</select>
1.8 注意:
- 在Oracle数据库中concat函数有且仅有两个参数,若有多个字符串需要拼接,则需要嵌套调用concat()函数。
- 如:concat(caoncat(‘’,‘’))
- 在xml中特殊符号需要转义。
采用xml转义字符进行转义(分号不能丢)
< -----> <
> -----> >
& -----> &
’ -----> '
" -----> &quou;
空格 -----> - 采用 <![CDATA[]]> 进行说明,将此内容不进行解析。
<if test="salary !=null">
<choose>
<when test="salary>50000">
where salary <![CDATA[>]]> #{salary}
</when>
加粗样式 < when test="salary>40000">
where salary > #{salary}
</when>
<otherwise>
where salary <![CDATA[<]]> 40000
</otherwise>
</choose>
</if>
1.9 #{} 与 ${}取值比较
- 都是取变量的值
- #{}在取值时,sql语句中变量值会替换成“?”,${} 直接替换成变量的值,因此**#{}** 处理时安全的,可以防止SQL注入,且sql是预编译的。
- ${} 方式一般用于传入数据对象,例如:表名,字段名。
例如:
select * from emp where empno=#{id}
select * from emp where empno=${id}
若id参数的值是1001, 则分别解析为:
#{}: select * from emp where empno='1001'
${}: select * from emp where empno=1001
若参数是"'empno=1001'or'1=1'",则分别解析为:
#{}: "'empno=1001'or'1=1'"
${}: 'empno=1001'or'1=1'