MyBatis之关于动态SQL解读
作者:不是很菜的菜
MyBatis动态SQL
MyBatis 动态SQL优点
MyBatis 的强大特性之一便是它的动态 SQL。
如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦,拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。
利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
1、if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分,例如
<select id="getByDept" resultType="City"> select * from provice <where> <if test="pid!=null"> pid=#{pid} </if> </where> </select>
当满足if中的条件是就会把if中条件也加入进sql语句中,否则不会。
例如当pid不能与null时,就会查找provice表中pid为传入的值的数据,但是当pid=null时,就会查找provice表中的所有数据。
2、choose (when, otherwise)
有些时候你并不想用到所有条件,但是有时候你又想用到这个条件,这个时候我们就可以用到choose(when,otherwise),这类似于java中的switch-case。
<select id="findStudentByChoose" resultType="City"> SELECT * from city where 1=1 <choose> <when test="cname!=null and cname!=''"> and cname like concat(concat('%',#{cname}),'%') </when> <when test="pid!=0"> and pid=#{pid} </when> <otherwise> <!-- 这里可以写,也可以不写代码--> </otherwise> </choose> </select>
这里提供了两种选择方式,你可以选择根据cname来查找,也可以选择根据pid来查找,但只要满足一个条件,其他条件则自动选择不满足,这样也可以避免无意义的查找。
(上面的1=1也可以不写,但是需要加入其他的东西,下面会提到)
3、trim(where)
前面例子已经合宜地解决了动态 SQL 问题,但是看下面的例子
<select id="getByDept" resultType="City"> select * from provice where <if test="pid!=null"> pid=#{pid} and </if> <if test="cname!=null and cname!=''"> and pname like concat(concat('%',#{cname}),'%') </if> </select>
当没有一个条件满足时,这会变成
select * from provice where
这样的sql语句并不正确,另外当第一个条件不满足,第二个条件满足时则会变成
select * from provice where and pname like concat(concat('%',#{cname}),'%')
这个查询也会失败。
这个问题不能简单的用条件句式来解决,这个时候我们就可以选择使用trim(where)
<select id="getByDept" resultType="City"> select * from provice where <trim suffix="" suffixOverrides="and"> <if test="pid!=null"> pid=#{pid} and </if> <if test="cname!=null and cname!=''"> and pname like concat(concat('%',#{cname}),'%') </if> </trim> </select>
where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。
而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。
如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。
4、foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。
List 实例将会以"list"作为键,而数组实例的键将是"array"。
例如:
<!--根据数组来找--> <select id="findStudentByArray" resultType="City"> SELECT * from city where pid in <foreach collection="array" item="pid" open="(" separator="," close=")"> #{pid} </foreach> </select> <!--根据列表来找--> <select id="findStudentByList" resultType="City"> select * from city WHERE pid in <foreach collection="list" item="pid" open="(" separator="," close=")"> #{pid} </foreach> </select> <!--根据map来找--> <select id="findStudentByMap" resultType="City"> SELECT * from city where cname like concat(concat('%',#{cname}),'%') and pid in <!--这里的name则根据前面传入的key值来确定--> <foreach collection="name" item="map" open="(" separator="," close=")"> #{map} </foreach> </select>
5、bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。
例如
<select id="bind" resultType="Provice"> <bind name="pro" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM porvice WHERE pid LIKE #{pro} </select>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。