动态 SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。
MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作
静态 SQL:静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的, 唯一变化的只要参数 。
动态 SQL:动态 SQL 语句是在应用程序运行时被编译和执行的,例如, 原生的jdbc模糊查询中使用的sql拼接时判断参数问题 , 这时参数是不固定的 , sql也是变化的 。
Mybatis对sql进行灵活操作,可以通过mybatis语法的判断对sql进行灵活封装,拼接
用于实现动态SQL的主要元素如下:
If
choose (when, otherwise)
trim (where, set)
Foreach
Bind
If
在查询语句中,当属性有name,age,email 时,只传入age 时,sql语句会出现前面多一个and
解决办法
方法一:为每个条件前加and 然后在where 后 添加1=1
方法二:使用where标签,自动去除前面多余的and ,但如果and加在每句的后面,则不行
方法三:使用trim标签(自定义截取规则)
<select id="getByIdAndName" resultType="com.bgs.bean.Employee">
SELECT * FROM `employee`
<where >
<!-- 1、where 1=1
2、<where>自动去除前面的and ,不能自动去除 后面的and
-->
<if test="name != null">
name=#{name}
</if>
<if test="age != 0">
and age=#{age}
</if>
<if test="email != null">
and email=#{email}
</if>
</where>
</select>
Trim (可以替换where,set功能)
prefix : 前缀
prefixOverrides: 前缀覆盖
suffix:后缀
suffixOverrides:后缀覆盖
suffixOverrides=“and”
<select id="getByTrim" resultType="com.bgs.bean.Employee">
SELECT * FROM `employee`
<trim prefix="where" prefixOverrides="and">
<if test="name != null">
name=#{name}
</if>
<if test="age != 0">
and age=#{age}
</if>
<if test="email != null">
and email=#{email}
</if>
</trim>
</select>
choose (when, otherwise)
有一个文本框,可以输入name,也可以输入age、email,如果输入的是name,则查找所有name符合输入的用户,如果输入的是age,则查找所有age符合输入的用户,如果输入的是email,则查找所有email符合输入的用户,如果输入的既不是name,也不是age,email,那么则通过查找id
<select id="getEmpByChoose" resultType="com.bgs.bean.Employee">
SELECT * FROM `employee` where 1=1
<choose>
<when test="name != null">
and name=#{name}
</when>
<when test="age != 0">
and age=#{age}
</when>
<when test="email !=null">
and email=#{email}
</when>
<otherwise>
and id = #{id}
</otherwise>
</choose>
</select>
Set
1.解决 <trim prefix="set" suffixOverrides=","></trim>
2.解决 set 自动去除后面的逗号 ,不能自动去除前面的逗号
<update id="updateEmp">
UPDATE `employee`
<set>
<if test="name != null">
name=#{name},
</if>
<if test="age !=0">
age=#{age},
</if>
<if test="email != null">
email=#{email},
</if>
</set>
where id = #{id}
</update>
Foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
案例一
collection : 要遍历的集合名
item: 遍历集合时每个元素的临时别名
separator : 每个元素之间的分隔符
open="" 以什么开始
close="" 以什么结束
for(Employee emp:ids){ }
<select id="getEmpByIn" resultType="com.bgs.bean.Employee">
SELECT * FROM `employee` WHERE id IN
<foreach collection="ids" item="id_item" open="("close=")" separator=",">
#{id_item}
</foreach>
</select>
案例二
你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。
当使用可迭代对象或者数组时,
index 是当前迭代的次数
item 的值是本次迭代获取的元素。
当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<!-- 批量插入 -->
<insert id="insertByForeach">
INSERT INTO employee(id,NAME,age) VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.id},#{emp.name},#{emp.age})
</foreach>
</insert>
bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="getEmpByBind" resultType="com.bgs.bean.Employee">
<bind name="liname" value="'%'+_parameter.name+'%'"/>
<!-- SELECT * FROM `employee` WHERE NAME LIKE #{liname} and email = #{_databaseId}-->
SELECT * FROM `employee` WHERE NAME LIKE #{liname} and email = #{email}
</select>