Mybatis动态sql
在创建sql语句时,有时会遇到 传入的参数为空的问题,也就是某些条件有时候不取值。这时就可以用动态sql来创建sql语句,不用自己拼接sql语句。
1.if 和 where 标签
在sql语句条件外面包一层 if 标签,if标签的 属性test 可以进行判断,当判断为true后才会把标签内部的条件拼接到sql语句中,为false就不拼接。
<mapper namespace="com.ztone.mapper.EmployeeMapper">
<select id="queryEmployee" resultType="employee">
select * from t_emp where
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null">
and emp_salary = #{salary}
</if>
</select>
</mapper>
这样就会出现几个问题
-
当第一个条件不满足,而第二个条件满足,那么sql语句就会变成这样
select * from t_emp where and emp_salary = #{salary}
-
当第一个条件和第二个条件都不满足,sql变成这样
select * from t_emp where
这两种情况形成的sql语句显然都是错误的,多了 where 或 and,这时候可以使用 where 标签
<mapper namespace="com.ztone.mapper.EmployeeMapper">
<select id="queryEmployee" resultType="employee">
select * from t_emp
<where>
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null">
and emp_salary = #{salary}
</if>
</where>
</select>
</mapper>
where标签可以
-
自动添加where关键字,当他发现where 标签中有if判断满足,就会自动添加where,否则不添加
-
自动去掉多余的 and 或 or 关键字
2.set标签
set标签和where类似,
在更新数据时会自动添加set关键字以及去掉多余的 “,”
<update id="updateEmployee">
update t_emp
<set>
<if test="empName != null">
emp_name = #{empName},
</if>
<if test="empSalary != null">
emp_salary = #{empSalary}
</if>
</set>
where emp_id = {empId}
</update>
如果不添加set标签,那么当第二个条件不满足,第一个条件满足时sql语句就会多一个 逗号
3.trim 标签
trim 标签可以替代 where 和 set 标签,动态添加关键字,去掉多余的关键字
trim的属性:
-
prefix:指定要动态添加的前缀
-
suffix:指定要动态添加的后缀
-
prefixOverrides:指定要动态去掉的前缀,使用 | 分隔多个值
-
suffixOverrides:指定要动态去掉的后缀,使用 | 分隔多个值
<select id="queryEmployee" resultType="employee">
select * from t_emp
<trim prefix="where" prefixOverrides="and">
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null">
and emp_salary = #{salary}
</if>
</trim>
</select>
4.choose/when/otherwise 标签
在多个分支中,只执行一个分支,和Java中的 switch case类似
如果都不满足,最后走 otherwise 标签
<select id="queryEmployee1" resultType="employee">
select * from t_emp
<where>
<choose>
<when test="name != null">
emp_name = #{name}
</when>
<when test="salary != null">
and emp_salary = #{salary}
</when>
<otherwise>1=1</otherwise>
</choose>
</where>
</select>
5.foreach标签
该标签是在sql语句中的遍历操作
foreach 的属性:
-
collection:要遍历的集合,也就是传进来的参数,这里最好用 @Param起名字,也可以用 arg0或list
-
open:遍历之前要追加的字符串
-
close:遍历之后要追加的字符串
-
separator:每次遍历的分隔符,最后一次遍历不会追加该分隔符
-
item:获取每个遍历项
案例:
查询多个员工。sql:select * from t_emp where emp_id in (1,2,3); 这里要遍历的部分是 括号内的id
<!-- List<Employee> queryBatch(@Param("ids") List<Integer> allId);-->
<select id="queryBatch" resultType="employee">
select * from t_emp where emp_id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
删除多个员工。sql:delete from t_emp where emp_id in (1,2,3) ;
<!-- int deleteBatch(@Param("ids") List<Integer> allId);-->
<delete id="deleteBatch">
delete from t_emp where emp_id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
插入多个员工。sql:insert into t_emp(emp_name,emp_salary) values ("xx",100),("ss",200); 这里遍历的是("xx",100)
<!-- int insertBatch(@Param("list") List<Employee> employees);-->
<insert id="insertBatch">
insert into t_emp(emp_name,emp_salary) values
<foreach collection="list" item="employee">
(#{employee.empName},#{employee.empSalary})
</foreach>
</insert>
更新多个员工。 sql:update t_emp set emp_name=#{empName},emp_salary=#{empSaraly} where emp_id={empId} 需要遍历的是整个sql语句
<!-- int updateBatch(@Param("list") List<Employee> employees);-->
<update id="updateBatch">
<foreach collection="list" item="employee">
update t_emp set emp_name=#{employee.empName},emp_salary=#{employee.empSaraly}
where emp_id={employee.empId}
</foreach>
</update>
如果要执行多个sql语句,需要在 数据库的url 中追加 allowMultiQueries=true 这个参数 允许多语句执行
6.sql片段
sql标签用来提取相同的sql语句,避免重复编写
sql标签的属性 id 代表该标签的名字,在用到该sql片段的地方,用 include标签 引入,include标签的属性refid的值就是sql标签的id值
<sql id="selectSql">
select * from t_emp
</sql>
<select id="queryEmployee" resultType="employee">
<include refid="selectSql"/>
<trim prefix="where" prefixOverrides="and">
<if test="name != null">
emp_name = #{name}
</if>
<if test="salary != null">
and emp_salary = #{salary}
</if>
</trim>
</select>